The out-of-the-box demo application flashed on all display modules before they are shipped.
Dependencies: DMBasicGUI DMSupport
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 EventQueue updateClockTimer(4*EVENTS_EVENT_SIZE); 00167 int updateClockTimerId = updateClockTimer.call_in(1000, onTimeoutEvent, &updateClock); 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(callback(this, &AppLauncherSpecial::onButtonEvent)); 00178 button.fall(callback(this, &AppLauncherSpecial::onButtonEvent)); 00179 00180 EventQueue buttonTimer(4*EVENTS_EVENT_SIZE); 00181 int buttonTimerId = buttonTimer.call_in(2000, onTimeoutEvent, &buttonTimeout); 00182 00183 // To prevent the "exit" click of a launched application to launch 00184 // a new application. This could happen on a multitouch display if 00185 // the launched applications' exit/ok/cancel button is located on 00186 // top of one of the buttons in the launcher. 00187 Timer tExit; 00188 tExit.start(); 00189 00190 // Wait for touches 00191 TouchPanel* touch = board->touchPanel(); 00192 touch->setListener(callback(this, &AppLauncherSpecial::onTouchEvent)); 00193 touch_coordinate_t coord; 00194 while (true) { 00195 ThisThread::flags_wait_all(APP_SIGID_TOUCH); 00196 if (_newTouchEvent) { 00197 if (buttonPressed) { 00198 // cancel 00199 buttonPressed = false; 00200 buttonTimer.cancel(buttonTimerId); 00201 } 00202 _newTouchEvent = false; 00203 if (touch->read(coord) != TouchPanel::TouchError_Ok) { 00204 log->printf("Failed to read touch coordinate\n"); 00205 continue; 00206 } 00207 // Process the touch coordinate for each button 00208 for (int i = 0; i < NumberOfButtons; i++) { 00209 if (_buttons[i] != NULL) { 00210 if (_buttons[i]->handle(coord.x, coord.y, coord.z > 0)) { 00211 _buttons[i]->draw(); 00212 } 00213 } 00214 } 00215 } else if (buttonTimeout) { 00216 if (board->buttonPressed()) { 00217 appToLaunch = CalibrationApp; 00218 } 00219 buttonPressed = false; 00220 buttonTimeout = false; 00221 } else if (_newButtonEvent) { 00222 _newButtonEvent = false; 00223 if (board->buttonPressed()) { 00224 buttonPressed = true; 00225 buttonTimer.dispatch(0); 00226 } else { 00227 buttonPressed = false; 00228 buttonTimer.cancel(buttonTimerId); 00229 } 00230 continue; 00231 } else if (updateClock) { 00232 updateClock = false; 00233 time_t seconds = time(0); 00234 sprintf(_currentTime, "%-25s", ctime(&seconds)); 00235 swim_put_text_xy(_win, _currentTime, clockXOff, clockYOff); 00236 continue; 00237 } 00238 00239 if (appToLaunch != NO_APPLICATION) { 00240 if (tExit.read_ms() < 500) { 00241 appToLaunch = NO_APPLICATION; 00242 continue; 00243 } 00244 App* a = NULL; 00245 if (_callback != NULL) { 00246 a = _callback(appToLaunch); 00247 } 00248 if (a != NULL) { 00249 if (a->setup()) { 00250 a->runToCompletion(); 00251 a->teardown(); 00252 } 00253 delete a; 00254 } 00255 tExit.reset(); 00256 appToLaunch = NO_APPLICATION; 00257 } 00258 } 00259 } 00260 00261 bool AppLauncherSpecial::teardown() 00262 { 00263 if (_win != NULL) { 00264 free(_win); 00265 _win = NULL; 00266 } 00267 if (_fb != NULL) { 00268 free(_fb); 00269 _fb = NULL; 00270 } 00271 for (int i = 0; i < NumberOfButtons; i++) { 00272 _buttons[i] = NULL; 00273 if (_buttons[i] != NULL) { 00274 delete _buttons[i]; 00275 _buttons[i] = NULL; 00276 } 00277 } 00278 if (_bgImg.pointerToFree != NULL) { 00279 free(_bgImg.pointerToFree); 00280 _bgImg.pointerToFree = NULL; 00281 } 00282 return true; 00283 } 00284 00285 void AppLauncherSpecial::setAppCreatorFunc(App*(*callback)(uint32_t buttonID)) 00286 { 00287 _callback = callback; 00288 } 00289 00290 bool AppLauncherSpecial::addButton(uint32_t buttonID, const char* caption) 00291 { 00292 int idx = _usedButtons++; 00293 int xspace = ((_disp->width() - ButtonColumns * ButtonWidth) / (ButtonColumns + 1)); 00294 int yspace = ((_disp->height() - TitleHeight - ButtonRows * ButtonHeight) / (ButtonRows + 1)); 00295 00296 _buttons[idx] = new Button(caption, (COLOR_T*)_fb, 00297 xspace + (ButtonWidth + xspace)*(idx%ButtonColumns), 00298 TitleHeight + yspace + (ButtonHeight + yspace)*(idx/ButtonColumns), 00299 ButtonWidth, ButtonHeight); 00300 _buttons[idx]->setAction(buttonClicked, buttonID); 00301 //_buttons[idx]->draw(); 00302 return true; 00303 } 00304 00305 bool AppLauncherSpecial::addImageButton(uint32_t buttonID, const char* imgUp, const char* imgDown) 00306 { 00307 return addImageButton(buttonID, NULL, BLACK, imgUp, imgDown); 00308 } 00309 00310 bool AppLauncherSpecial::addImageButton(uint32_t buttonID, const char* caption, COLOR_T color, const char* imgUp, const char* imgDown) 00311 { 00312 int idx = _usedButtons++; 00313 int xspace = ((_disp->width() - ButtonColumns * _iconWidth) / (ButtonColumns + 1)); 00314 int yspace = ((_disp->height() - TitleHeight - ButtonRows * _iconHeight) / (ButtonRows + 1)); 00315 00316 ImageButton* img = new ImageButton((COLOR_T*)_fb, 00317 xspace + (_iconWidth + xspace)*(idx%ButtonColumns), 00318 TitleHeight + yspace + (_iconHeight + yspace)*(idx/ButtonColumns), 00319 _iconWidth, _iconHeight, caption, color); 00320 if (img->loadImages(imgUp, imgDown)) { 00321 _buttons[idx] = img; 00322 _buttons[idx]->setAction(buttonClicked, buttonID); 00323 //_buttons[idx]->draw(); 00324 return true; 00325 } else { 00326 //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown); 00327 return false; 00328 } 00329 } 00330 00331 bool AppLauncherSpecial::addImageButton(uint32_t buttonID, const unsigned char* imgUp, unsigned int imgUpSize, const unsigned char* imgDown, unsigned int imgDownSize) 00332 { 00333 return addImageButton(buttonID, NULL, BLACK, imgUp, imgUpSize, imgDown, imgDownSize); 00334 } 00335 00336 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) 00337 { 00338 int idx = _usedButtons++; 00339 int xspace = ((_disp->width() - ButtonColumns * _iconWidth) / (ButtonColumns + 1)); 00340 int yspace = ((_disp->height() - TitleHeight - ButtonRows * _iconHeight) / (ButtonRows + 1)); 00341 00342 ImageButton* img = new ImageButton((COLOR_T*)_fb, 00343 xspace + (_iconWidth + xspace)*(idx%ButtonColumns), 00344 TitleHeight + yspace + (_iconHeight + yspace)*(idx/ButtonColumns), 00345 _iconWidth, _iconHeight, caption, color); 00346 img->setTransparency(RED); 00347 if (img->loadImages(imgUp, imgUpSize, imgDown, imgDownSize)) { 00348 _buttons[idx] = img; 00349 _buttons[idx]->setAction(buttonClicked, buttonID); 00350 //_buttons[idx]->draw(); 00351 return true; 00352 } else { 00353 //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown); 00354 return false; 00355 } 00356 } 00357 00358 bool AppLauncherSpecial::addImageButton(uint32_t buttonID, const char* caption, COLOR_T color, Resource* resUp, Resource* resDown) 00359 { 00360 int idx = _usedButtons++; 00361 int xspace = ((_disp->width() - ButtonColumns * _iconWidth) / (ButtonColumns + 1)); 00362 int yspace = ((_disp->height() - TitleHeight - ButtonRows * _iconHeight) / (ButtonRows + 1)); 00363 00364 ImageButton* img = new ImageButton((COLOR_T*)_fb, 00365 xspace + (_iconWidth + xspace)*(idx%ButtonColumns), 00366 TitleHeight + yspace + (_iconHeight + yspace)*(idx/ButtonColumns), 00367 _iconWidth, _iconHeight, caption, color); 00368 if (img->loadImages(resUp, resDown)) { 00369 _buttons[idx] = img; 00370 _buttons[idx]->setAction(buttonClicked, buttonID); 00371 //_buttons[idx]->draw(); 00372 return true; 00373 } else { 00374 //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown); 00375 return false; 00376 } 00377 } 00378 00379 void AppLauncherSpecial::addResource(Resources id, Resource* res) 00380 { 00381 _resBg = res; 00382 } 00383
Generated on Wed Jul 13 2022 05:17:56 by 1.7.2