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.
Dependencies: DMBasicGUI DMSupport
Fork of lpc4088_displaymodule_shipped_demo by
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
Generated on Wed Jul 13 2022 21:47:07 by
