Chris Womack / sampleGUI

Dependencies:   DMBasicGUI DMSupport

Fork of lpc4088_displaymodule_shipped_demo by Embedded Artists

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AppLauncherSpecial.cpp Source File

AppLauncherSpecial.cpp

00001 /*
00002  *  Copyright 2014 Embedded Artists AB
00003  *
00004  *  Licensed under the Apache License, Version 2.0 (the "License");
00005  *  you may not use this file except in compliance with the License.
00006  *  You may obtain a copy of the License at
00007  *
00008  *    http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  *  Unless required by applicable law or agreed to in writing, software
00011  *  distributed under the License is distributed on an "AS IS" BASIS,
00012  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *  See the License for the specific language governing permissions and
00014  *  limitations under the License.
00015  */
00016 
00017 
00018 #include "mbed.h"
00019 #include "AppLauncherSpecial.h"
00020 #include "lpc_swim_image.h"
00021 #include "lpc_swim_font.h"
00022 #include "Button.h"
00023 #include "ImageButton.h"
00024 #include "image_data.h"
00025 
00026 /******************************************************************************
00027  * Defines and typedefs
00028  *****************************************************************************/
00029  
00030 #define APP_PREFIX  "[Launcher*] "
00031 
00032 #define NO_APPLICATION  (-1)
00033 
00034 #define APP_SIGID_TOUCH  0x1
00035 
00036 /******************************************************************************
00037  * Private variables
00038  *****************************************************************************/
00039 
00040 static int appToLaunch = NO_APPLICATION;
00041 static osThreadId appThread;
00042 
00043 /******************************************************************************
00044  * Private functions
00045  *****************************************************************************/
00046 
00047 static void buttonClicked(uint32_t x)
00048 {
00049     if (appToLaunch == NO_APPLICATION) {
00050         appToLaunch = (int)x;
00051     }
00052 }
00053 
00054 void AppLauncherSpecial::draw()
00055 {
00056     // Prepare fullscreen
00057     swim_window_open(_win, 
00058                      _disp->width(), _disp->height(),         // full size
00059                      (COLOR_T*)_fb,
00060                      0,0,_disp->width()-1, _disp->height()-1, // window position and size
00061                      0,                                     // border
00062                      BLACK, WHITE, /*WHITE, BLACK,*/ BLACK);                    // colors: pen, backgr, forgr
00063     //swim_set_title(_win, "Demo Program", WHITE);
00064 
00065     swim_put_image(_win, _bgImg.pixels, _bgImg.width, _bgImg.height);
00066     
00067     if (_supportsCalibration) {
00068       const char* msg = "(Press physical UserButton >2s to calibrate touch)";
00069       int w, h;
00070       swim_get_string_bounds(_win, msg, &w, &h);
00071       swim_set_font_transparency(_win, 0); // 0=Transparent, 1=Opaque
00072       swim_put_text_xy(_win, msg, (_disp->width()-w)/2, _disp->height()-(3*h)/2);
00073       swim_set_font_transparency(_win, 1); // 0=Transparent, 1=Opaque
00074     }
00075     
00076     for (int i = 0; i < _usedButtons; i++) {
00077         _buttons[i]->draw();
00078     }
00079 }
00080 
00081 void AppLauncherSpecial::onTouchEvent()
00082 {
00083     _newTouchEvent = true;
00084     osSignalSet(appThread, APP_SIGID_TOUCH);
00085 }
00086 
00087 void AppLauncherSpecial::onButtonEvent()
00088 {
00089     _newButtonEvent = true;
00090     osSignalSet(appThread, APP_SIGID_TOUCH);
00091 }
00092 
00093 static void onTimeoutEvent(void const* arg)
00094 {
00095     *((bool*)arg) = true;
00096     osSignalSet(appThread, APP_SIGID_TOUCH);
00097 }
00098 
00099 /******************************************************************************
00100  * Public functions
00101  *****************************************************************************/
00102 
00103 AppLauncherSpecial::AppLauncherSpecial(int iconWidth, int iconHeight) : 
00104     _disp(NULL), _win(NULL), _fb(NULL), _usedButtons(0), 
00105     _resBg(NULL), _iconWidth(iconWidth), _iconHeight(iconHeight)
00106 {
00107     _bgImg.pointerToFree = NULL;
00108     _bgImg.pixels = NULL;
00109     _currentTime[0] = '\0';
00110 
00111     for (int i = 0; i < NumberOfButtons; i++) {
00112         _buttons[i] = NULL;
00113     }
00114     bool r;
00115     int n;
00116     if (DMBoard::instance().touchPanel()->info(&r, &n, &_supportsCalibration) != TouchPanel::TouchError_Ok) {
00117       _supportsCalibration = false;
00118     }
00119 }
00120 
00121 AppLauncherSpecial::~AppLauncherSpecial()
00122 {
00123     teardown();
00124 }
00125 
00126 bool AppLauncherSpecial::setup()
00127 {
00128     RtosLog* log = DMBoard::instance().logger();
00129 
00130     _disp = DMBoard::instance().display();
00131     _win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T));
00132     _fb = _disp->allocateFramebuffer();
00133     
00134     if (_win == NULL || _fb == NULL) {
00135         log->printf(APP_PREFIX"Failed to allocate memory for framebuffer\r\n");
00136         return false;
00137     }
00138     
00139     if (Image::decode(_resBg, Image::RES_16BIT, &_bgImg) != 0) {
00140         log->printf(APP_PREFIX"Failed to load background image\n");
00141         return false;
00142     }
00143     
00144     return true;
00145 }
00146 
00147 void AppLauncherSpecial::runToCompletion()
00148 {
00149     DMBoard* board = &DMBoard::instance();
00150     RtosLog* log = board->logger();
00151     
00152     appThread = osThreadGetId();
00153 
00154     // Draw something on the framebuffer before using it so that it doesn't look garbled
00155     draw();
00156     
00157     // Start display in default mode (16-bit)
00158     Display::DisplayError disperr = _disp->powerUp(_fb);
00159     if (disperr != Display::DisplayError_Ok) {
00160         log->printf(APP_PREFIX"Failed to initialize the display, got error %d\r\n", disperr);
00161         return;
00162     }
00163     
00164     // Render the current time in the upper right corner once every second
00165     bool updateClock = false;
00166     RtosTimer updateClockTimer(onTimeoutEvent, osTimerPeriodic, &updateClock);
00167     updateClockTimer.start(1000);
00168     int clockXOff, clockYOff;
00169     swim_get_string_bounds(_win, "Fri Mar 20 10:32:58 2015", &clockXOff, &clockYOff);
00170     clockXOff = _win->xpvmax - clockXOff - 20;
00171     clockYOff = 5;
00172     
00173     // To keep track of the button pushes
00174     bool buttonPressed = false;
00175     bool buttonTimeout = false;
00176     InterruptIn button(P2_10);
00177     button.rise(this, &AppLauncherSpecial::onButtonEvent);
00178     button.fall(this, &AppLauncherSpecial::onButtonEvent);
00179     RtosTimer  buttonTimer(onTimeoutEvent, osTimerOnce, &buttonTimeout);
00180     
00181     // To prevent the "exit" click of a launched application to launch
00182     // a new application. This could happen on a multitouch display if
00183     // the launched applications' exit/ok/cancel button is located on
00184     // top of one of the buttons in the launcher.
00185     Timer tExit;
00186     tExit.start();
00187     
00188     // Wait for touches
00189     TouchPanel* touch = board->touchPanel();
00190     touch->setListener(new FunctionPointer(this, &AppLauncherSpecial::onTouchEvent));
00191     touch_coordinate_t coord;
00192     while (true) {
00193         Thread::signal_wait(APP_SIGID_TOUCH);
00194         if (_newTouchEvent) {
00195           if (buttonPressed) {
00196             // cancel
00197             buttonPressed = false;
00198             buttonTimer.stop();
00199           }
00200           _newTouchEvent = false;
00201           if (touch->read(coord) != TouchPanel::TouchError_Ok) {
00202             log->printf("Failed to read touch coordinate\n");
00203             continue;
00204           }
00205           // Process the touch coordinate for each button
00206           for (int i = 0; i < NumberOfButtons; i++) {
00207             if (_buttons[i] != NULL) {
00208               if (_buttons[i]->handle(coord.x, coord.y, coord.z > 0)) {
00209                 _buttons[i]->draw();
00210               }
00211             }
00212           }
00213         } else if (buttonTimeout) {
00214           if (board->buttonPressed()) {
00215             appToLaunch = CalibrationApp;
00216           }
00217           buttonPressed = false;
00218           buttonTimeout = false;
00219         } else if (_newButtonEvent) {
00220           _newButtonEvent = false;
00221           if (board->buttonPressed()) {
00222             buttonPressed = true;
00223             buttonTimer.start(2000);
00224           } else {
00225             buttonPressed = false;
00226             buttonTimer.stop();
00227           }
00228           continue;
00229         } else if (updateClock) {
00230           updateClock = false;
00231           time_t seconds = time(0);
00232           sprintf(_currentTime, "%-25s", ctime(&seconds));
00233           swim_put_text_xy(_win, _currentTime, clockXOff, clockYOff);
00234           continue;
00235         }
00236         
00237         if (appToLaunch != NO_APPLICATION) {
00238           if (tExit.read_ms() < 500) {
00239             appToLaunch = NO_APPLICATION;
00240             continue;
00241           }
00242           App* a = NULL;
00243           if (_callback != NULL) {
00244             a = _callback(appToLaunch);
00245           }
00246           if (a != NULL) {
00247             if (a->setup()) {
00248               a->runToCompletion();
00249               a->teardown();
00250             }
00251             delete a;            
00252           }
00253           tExit.reset();
00254           appToLaunch = NO_APPLICATION;
00255         }
00256     }
00257 }
00258 
00259 bool AppLauncherSpecial::teardown()
00260 {
00261     if (_win != NULL) {
00262         free(_win);
00263         _win = NULL;
00264     }
00265     if (_fb != NULL) {
00266         free(_fb);
00267         _fb = NULL;
00268     }
00269     for (int i = 0; i < NumberOfButtons; i++) {
00270         _buttons[i] = NULL;
00271         if (_buttons[i] != NULL) {
00272             delete _buttons[i];
00273             _buttons[i] = NULL;
00274         }
00275     }
00276     if (_bgImg.pointerToFree != NULL) {
00277         free(_bgImg.pointerToFree);
00278         _bgImg.pointerToFree = NULL;
00279     }    
00280     return true;
00281 }
00282 
00283 void AppLauncherSpecial::setAppCreatorFunc(App*(*callback)(uint32_t buttonID))
00284 {
00285     _callback = callback;
00286 }
00287 
00288 bool AppLauncherSpecial::addButton(uint32_t buttonID, const char* caption)
00289 {
00290     int idx = _usedButtons++;
00291     int xspace = ((_disp->width() - ButtonColumns * ButtonWidth) / (ButtonColumns + 1));
00292     int yspace = ((_disp->height() - TitleHeight - ButtonRows * ButtonHeight) / (ButtonRows + 1));
00293     
00294     _buttons[idx] = new Button(caption, (COLOR_T*)_fb, 
00295                               xspace + (ButtonWidth + xspace)*(idx%ButtonColumns), 
00296                               TitleHeight + yspace + (ButtonHeight + yspace)*(idx/ButtonColumns), 
00297                               ButtonWidth, ButtonHeight);
00298     _buttons[idx]->setAction(buttonClicked, buttonID);
00299     //_buttons[idx]->draw();
00300     return true;
00301 }
00302 
00303 bool AppLauncherSpecial::addImageButton(uint32_t buttonID, const char* imgUp, const char* imgDown)
00304 {
00305     return addImageButton(buttonID, NULL, BLACK, imgUp, imgDown);
00306 }
00307 
00308 bool AppLauncherSpecial::addImageButton(uint32_t buttonID, const char* caption, COLOR_T color, const char* imgUp, const char* imgDown)
00309 {
00310     int idx = _usedButtons++;
00311     int xspace = ((_disp->width() - ButtonColumns * _iconWidth) / (ButtonColumns + 1));
00312     int yspace = ((_disp->height() - TitleHeight - ButtonRows * _iconHeight) / (ButtonRows + 1));
00313     
00314     ImageButton* img =  new ImageButton((COLOR_T*)_fb, 
00315                               xspace + (_iconWidth + xspace)*(idx%ButtonColumns), 
00316                               TitleHeight + yspace + (_iconHeight + yspace)*(idx/ButtonColumns), 
00317                               _iconWidth, _iconHeight, caption, color);
00318     if (img->loadImages(imgUp, imgDown)) {
00319       _buttons[idx] = img;
00320       _buttons[idx]->setAction(buttonClicked, buttonID);
00321       //_buttons[idx]->draw();
00322       return true;
00323     } else {
00324       //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown);
00325       return false;
00326     }
00327 }
00328 
00329 bool AppLauncherSpecial::addImageButton(uint32_t buttonID, const unsigned char* imgUp, unsigned int imgUpSize, const unsigned char* imgDown, unsigned int imgDownSize)
00330 {
00331     return addImageButton(buttonID, NULL, BLACK, imgUp, imgUpSize, imgDown, imgDownSize);
00332 }
00333 
00334 bool AppLauncherSpecial::addImageButton(uint32_t buttonID, const char* caption, COLOR_T color, const unsigned char* imgUp, unsigned int imgUpSize, const unsigned char* imgDown, unsigned int imgDownSize)
00335 {
00336     int idx = _usedButtons++;
00337     int xspace = ((_disp->width() - ButtonColumns * _iconWidth) / (ButtonColumns + 1));
00338     int yspace = ((_disp->height() - TitleHeight - ButtonRows * _iconHeight) / (ButtonRows + 1));
00339     
00340     ImageButton* img =  new ImageButton((COLOR_T*)_fb, 
00341                               xspace + (_iconWidth + xspace)*(idx%ButtonColumns), 
00342                               TitleHeight + yspace + (_iconHeight + yspace)*(idx/ButtonColumns), 
00343                               _iconWidth, _iconHeight, caption, color);
00344     img->setTransparency(RED);
00345     if (img->loadImages(imgUp, imgUpSize, imgDown, imgDownSize)) {
00346       _buttons[idx] = img;
00347       _buttons[idx]->setAction(buttonClicked, buttonID);
00348       //_buttons[idx]->draw();
00349       return true;
00350     } else {
00351       //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown);
00352       return false;
00353     }
00354 }
00355 
00356 bool AppLauncherSpecial::addImageButton(uint32_t buttonID, const char* caption, COLOR_T color, Resource* resUp, Resource* resDown)
00357 {
00358     int idx = _usedButtons++;
00359     int xspace = ((_disp->width() - ButtonColumns * _iconWidth) / (ButtonColumns + 1));
00360     int yspace = ((_disp->height() - TitleHeight - ButtonRows * _iconHeight) / (ButtonRows + 1));
00361     
00362     ImageButton* img =  new ImageButton((COLOR_T*)_fb, 
00363                               xspace + (_iconWidth + xspace)*(idx%ButtonColumns), 
00364                               TitleHeight + yspace + (_iconHeight + yspace)*(idx/ButtonColumns), 
00365                               _iconWidth, _iconHeight, caption, color);
00366     if (img->loadImages(resUp, resDown)) {
00367       _buttons[idx] = img;
00368       _buttons[idx]->setAction(buttonClicked, buttonID);
00369       //_buttons[idx]->draw();
00370       return true;
00371     } else {
00372       //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown);
00373       return false;
00374     }
00375 }
00376 
00377 void AppLauncherSpecial::addResource(Resources id, Resource* res)
00378 {
00379     _resBg = res;
00380 }
00381