Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of DMBasicGUI by
Application/AppLauncher.cpp
- Committer:
- embeddedartists
- Date:
- 2014-12-21
- Revision:
- 5:f4de114c31c3
- Parent:
- 3:3fabfe3339b8
- Child:
- 8:19a6b70d42b1
File content as of revision 5:f4de114c31c3:
/*
 *  Copyright 2014 Embedded Artists AB
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
#include "mbed.h"
#include "AppLauncher.h"
#include "lpc_swim_font.h"
#include "Button.h"
#include "ImageButton.h"
/******************************************************************************
 * Defines and typedefs
 *****************************************************************************/
 
#define APP_PREFIX  "[Launcher] "
#define NO_APPLICATION  (-1)
//typedef enum {
//    NoApplication = -1,
//    SettingsApp   =  0,
//    ColorPicker,
//    TouchTestApp,
//    ImageViewerApp,
//    SlideshowApp,
//    //TouchGFXApp,
//    //EmWinApp,
//    Placeholder    =  99,
//    CalibrationApp = 100,
//} AppID_t;
/******************************************************************************
 * Private variables
 *****************************************************************************/
static int appToLaunch = NO_APPLICATION;
/******************************************************************************
 * Private functions
 *****************************************************************************/
static void buttonClicked(uint32_t x)
{
    if (appToLaunch == NO_APPLICATION) {
        appToLaunch = (int)x;
    }
}
void AppLauncher::draw()
{
    // Prepare fullscreen
    swim_window_open(_win, 
                     _disp->width(), _disp->height(),         // full size
                     (COLOR_T*)_fb,
                     0,0,_disp->width()-1, _disp->height()-1, // window position and size
                     1,                                     // border
                     WHITE, BLACK, BLACK);                    // colors: pen, backgr, forgr
    swim_set_title(_win, "Demo Program", BLACK);
    const char* msg = "(Press physical UserButton >2s to calibrate touch)";
    int w, h;
    swim_get_string_bounds(_win, msg, &w, &h);
    swim_put_text_xy(_win, msg, (_disp->width()-w)/2, _disp->height()-h*4);
    
    for (int i = 0; i < _usedButtons; i++) {
        _buttons[i]->draw();
    }
}
/******************************************************************************
 * Public functions
 *****************************************************************************/
AppLauncher::AppLauncher() : _disp(NULL), _win(NULL), _fb(NULL), _usedButtons(0)
{
    for (int i = 0; i < NumberOfButtons; i++) {
        _buttons[i] = NULL;
    }
}
AppLauncher::~AppLauncher()
{
    teardown();
}
bool AppLauncher::setup()
{
    RtosLog* log = DMBoard::instance().logger();
    _disp = DMBoard::instance().display();
    _win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T));
    _fb = _disp->allocateFramebuffer();
    
    if (_win == NULL || _fb == NULL) {
        log->printf(APP_PREFIX"Failed to allocate memory for framebuffer\r\n");
        return false;
    }
    
    return true;
}
void AppLauncher::runToCompletion()
{
    DMBoard* board = &DMBoard::instance();
    RtosLog* log = board->logger();
    // Draw something on the framebuffer before using it so that it doesn't look garbled
    draw();
    
    // Start display in default mode (16-bit)
    Display::DisplayError disperr = _disp->powerUp(_fb);
    if (disperr != Display::DisplayError_Ok) {
        log->printf(APP_PREFIX"Failed to initialize the display, got error %d\r\n", disperr);
        return;
    }
    // To keep track of the button pushes
    Timer buttonTimer;
    bool buttonPressed = false;
    
    // Wait for touches
    TouchPanel* touch = board->touchPanel();
    TouchPanel::touchCoordinate_t coord;
    while(touch->read(coord) == TouchPanel::TouchError_Ok) {
        
        // Process the touch coordinate for each button
        for (int i = 0; i < NumberOfButtons; i++) {
            if (_buttons[i] != NULL) {
                if (_buttons[i]->handle(coord.x, coord.y, coord.z > 0)) {
                    _buttons[i]->draw();
                }
            }
        }
        
        // Check if the physical USER button on the board has been pressed
        if (appToLaunch == NO_APPLICATION) {
            if (board->buttonPressed()) {
                if (buttonPressed) {
                    if (buttonTimer.read_ms() > 2000) {
                        // User has pressed the button more than two seconds.
                        // Start calibration application
                        appToLaunch = CalibrationApp;
                        buttonTimer.stop();
                        buttonPressed = false;
                    }
                } else {
                    buttonTimer.reset();
                    buttonTimer.start();
                    buttonPressed = true;
                }
            } else if (buttonPressed) {
                buttonTimer.stop();
                buttonPressed = false;
            }
        } else {
            // pressing the display buttons take precedence so disregard the
            // USER button
            buttonTimer.stop();
            buttonPressed = false;
        }
        
        if (appToLaunch != NO_APPLICATION) {
            App* a = NULL;
            if (_callback != NULL) {
                a = _callback(appToLaunch);
            }
            if (a != NULL) {
                if (a->setup()) {
                    a->runToCompletion();
                    a->teardown();
                }
                delete a;
            }
            appToLaunch = NO_APPLICATION;
        }
    }
}
bool AppLauncher::teardown()
{
    if (_win != NULL) {
        free(_win);
        _win = NULL;
    }
    if (_fb != NULL) {
        free(_fb);
        _fb = NULL;
    }
    for (int i = 0; i < NumberOfButtons; i++) {
        _buttons[i] = NULL;
        if (_buttons[i] != NULL) {
            delete _buttons[i];
            _buttons[i] = NULL;
        }
    }
    return true;
}
void AppLauncher::setAppCreatorFunc(App*(*callback)(uint32_t buttonID))
{
    _callback = callback;
}
bool AppLauncher::addButton(uint32_t buttonID, const char* caption)
{
    int idx = _usedButtons++;
    int xspace = ((_disp->width() - ButtonColumns * ButtonWidth) / (ButtonColumns + 1));
    int yspace = ((_disp->height() - TitleHeight - ButtonRows * ButtonHeight) / (ButtonRows + 1));
    
    _buttons[idx] = new Button(caption, (COLOR_T*)_fb, 
                              xspace + (ButtonWidth + xspace)*(idx%ButtonColumns), 
                              TitleHeight + yspace + (ButtonHeight + yspace)*(idx/ButtonColumns), 
                              ButtonWidth, ButtonHeight);
    _buttons[idx]->setAction(buttonClicked, buttonID);
    //_buttons[idx]->draw();
    return true;
}
bool AppLauncher::addImageButton(uint32_t buttonID, const char* imgUp, const char* imgDown)
{
    int idx = _usedButtons++;
    int xspace = ((_disp->width() - ButtonColumns * 64) / (ButtonColumns + 1));
    int yspace = ((_disp->height() - TitleHeight - ButtonRows * 64) / (ButtonRows + 1));
    
    ImageButton* img =  new ImageButton((COLOR_T*)_fb, 
                              xspace + (64 + xspace)*(idx%ButtonColumns), 
                              TitleHeight + yspace + (64 + yspace)*(idx/ButtonColumns), 
                              64, 64);
    if (img->loadImages(imgUp, imgDown)) {
      _buttons[idx] = img;
      _buttons[idx]->setAction(buttonClicked, buttonID);
      //_buttons[idx]->draw();
      return true;
    } else {
      //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown);
      return false;
    }
}
bool AppLauncher::addImageButton(uint32_t buttonID, const unsigned char* imgUp, unsigned int imgUpSize, const unsigned char* imgDown, unsigned int imgDownSize)
{
    int idx = _usedButtons++;
    int xspace = ((_disp->width() - ButtonColumns * 64) / (ButtonColumns + 1));
    int yspace = ((_disp->height() - TitleHeight - ButtonRows * 64) / (ButtonRows + 1));
    
    ImageButton* img =  new ImageButton((COLOR_T*)_fb, 
                              xspace + (64 + xspace)*(idx%ButtonColumns), 
                              TitleHeight + yspace + (64 + yspace)*(idx/ButtonColumns), 
                              64, 64);
    if (img->loadImages(imgUp, imgUpSize, imgDown, imgDownSize)) {
      _buttons[idx] = img;
      _buttons[idx]->setAction(buttonClicked, buttonID);
      //_buttons[idx]->draw();
      return true;
    } else {
      //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown);
      return false;
    }
}
            
    