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
AppLauncher.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 "AppLauncher.h" 00020 #include "lpc_swim_font.h" 00021 #include "Button.h" 00022 #include "ImageButton.h" 00023 #include "lpc_winfreesystem14x16.h" 00024 00025 /****************************************************************************** 00026 * Defines and typedefs 00027 *****************************************************************************/ 00028 00029 #define APP_PREFIX "[Launcher] " 00030 00031 #define NO_APPLICATION (-1) 00032 00033 #define APP_SIGID_TOUCH 0x1 00034 00035 /****************************************************************************** 00036 * Private variables 00037 *****************************************************************************/ 00038 00039 static int appToLaunch = NO_APPLICATION; 00040 static osThreadId appThread; 00041 00042 /****************************************************************************** 00043 * Private functions 00044 *****************************************************************************/ 00045 00046 static void buttonClicked(uint32_t x) 00047 { 00048 if (appToLaunch == NO_APPLICATION) { 00049 appToLaunch = (int)x; 00050 } 00051 } 00052 00053 void AppLauncher::draw() 00054 { 00055 // Prepare fullscreen 00056 swim_window_open(_win, 00057 _disp->width(), _disp->height(), // full size 00058 (COLOR_T*)_fb, 00059 0,0,_disp->width()-1, _disp->height()-1, // window position and size 00060 0, // border 00061 BLACK, WHITE, BLACK); // colors: pen, backgr, forgr 00062 swim_set_font(_win, (FONT_T*)&font_winfreesys14x16); 00063 00064 if (_supportsCalibration) { 00065 const char* msg = "(Press physical UserButton >2s to calibrate touch)"; 00066 int w, h; 00067 swim_get_string_bounds(_win, msg, &w, &h); 00068 //swim_put_text_xy(_win, msg, (_disp->width()-w)/2, _disp->height()-h*4); 00069 } 00070 00071 for (int i = 0; i < _usedButtons; i++) { 00072 _buttons[i]->draw(); 00073 } 00074 } 00075 00076 void AppLauncher::onTouchEvent() 00077 { 00078 _newTouchEvent = true; 00079 osSignalSet(appThread, APP_SIGID_TOUCH); 00080 } 00081 00082 void AppLauncher::onButtonEvent() 00083 { 00084 _newButtonEvent = true; 00085 osSignalSet(appThread, APP_SIGID_TOUCH); 00086 } 00087 00088 static void onTimeoutEvent(void const* arg) 00089 { 00090 *((bool*)arg) = true; 00091 osSignalSet(appThread, APP_SIGID_TOUCH); 00092 } 00093 00094 /****************************************************************************** 00095 * Public functions 00096 *****************************************************************************/ 00097 00098 AppLauncher::AppLauncher() : _disp(NULL), _win(NULL), _fb(NULL), _usedButtons(0) 00099 { 00100 for (int i = 0; i < NumberOfButtons; i++) { 00101 _buttons[i] = NULL; 00102 } 00103 bool r; 00104 int n; 00105 if (DMBoard::instance().touchPanel()->info(&r, &n, &_supportsCalibration) != TouchPanel::TouchError_Ok) { 00106 _supportsCalibration = false; 00107 } 00108 } 00109 00110 AppLauncher::~AppLauncher() 00111 { 00112 teardown(); 00113 } 00114 00115 bool AppLauncher::setup() 00116 { 00117 RtosLog* log = DMBoard::instance().logger(); 00118 00119 _disp = DMBoard::instance().display(); 00120 _win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T)); 00121 _fb = _disp->allocateFramebuffer(); 00122 00123 if (_win == NULL || _fb == NULL) { 00124 log->printf(APP_PREFIX"Failed to allocate memory for framebuffer\r\n"); 00125 return false; 00126 } 00127 00128 return true; 00129 } 00130 00131 void AppLauncher::runToCompletion() 00132 { 00133 DMBoard* board = &DMBoard::instance(); 00134 RtosLog* log = board->logger(); 00135 00136 appThread = osThreadGetId(); 00137 00138 // Draw something on the framebuffer before using it so that it doesn't look garbled 00139 draw(); 00140 00141 // Start display in default mode (16-bit) 00142 Display::DisplayError disperr = _disp->powerUp(_fb); 00143 if (disperr != Display::DisplayError_Ok) { 00144 log->printf(APP_PREFIX"Failed to initialize the display, got error %d\r\n", disperr); 00145 return; 00146 } 00147 00148 // To keep track of the button pushes 00149 bool buttonPressed = false; 00150 bool buttonTimeout = false; 00151 InterruptIn button(P2_10); 00152 button.rise(this, &AppLauncher::onButtonEvent); 00153 button.fall(this, &AppLauncher::onButtonEvent); 00154 RtosTimer buttonTimer(onTimeoutEvent, osTimerOnce, &buttonTimeout); 00155 00156 // Wait for touches 00157 TouchPanel* touch = board->touchPanel(); 00158 FunctionPointer* fpOld = touch->setListener(new FunctionPointer(this, &AppLauncher::onTouchEvent)); 00159 touch_coordinate_t coord; 00160 while (true) { 00161 Thread::signal_wait(APP_SIGID_TOUCH); 00162 if (_newTouchEvent) { 00163 if (buttonPressed) { 00164 // cancel 00165 buttonPressed = false; 00166 buttonTimer.stop(); 00167 } 00168 _newTouchEvent = false; 00169 if (touch->read(coord) != TouchPanel::TouchError_Ok) { 00170 log->printf("Failed to read touch coordinate\n"); 00171 continue; 00172 } 00173 // Process the touch coordinate for each button 00174 for (int i = 0; i < NumberOfButtons; i++) { 00175 if (_buttons[i] != NULL) { 00176 if (_buttons[i]->handle(coord.x, coord.y, coord.z > 0)) { 00177 _buttons[i]->draw(); 00178 } 00179 } 00180 } 00181 } else if (buttonTimeout) { 00182 if (board->buttonPressed()) { 00183 appToLaunch = CalibrationApp; 00184 } 00185 buttonPressed = false; 00186 buttonTimeout = false; 00187 } else if (_newButtonEvent) { 00188 _newButtonEvent = false; 00189 if (board->buttonPressed()) { 00190 buttonPressed = true; 00191 buttonTimer.start(2000); 00192 } else { 00193 buttonPressed = false; 00194 buttonTimer.stop(); 00195 } 00196 continue; 00197 } 00198 00199 if (appToLaunch != NO_APPLICATION) { 00200 App* a = NULL; 00201 if (_callback != NULL) { 00202 a = _callback(appToLaunch); 00203 } 00204 if (a != NULL) { 00205 if (a->setup()) { 00206 a->runToCompletion(); 00207 a->teardown(); 00208 } 00209 delete a; 00210 } 00211 appToLaunch = NO_APPLICATION; 00212 } 00213 } 00214 00215 restore old touch listener (get our listener in return) 00216 fpOld = touch->setListener(fpOld); 00217 delete fpOld; 00218 } 00219 00220 bool AppLauncher::teardown() 00221 { 00222 if (_win != NULL) { 00223 free(_win); 00224 _win = NULL; 00225 } 00226 if (_fb != NULL) { 00227 free(_fb); 00228 _fb = NULL; 00229 } 00230 for (int i = 0; i < NumberOfButtons; i++) { 00231 _buttons[i] = NULL; 00232 if (_buttons[i] != NULL) { 00233 delete _buttons[i]; 00234 _buttons[i] = NULL; 00235 } 00236 } 00237 return true; 00238 } 00239 00240 void AppLauncher::setAppCreatorFunc(App*(*callback)(uint32_t buttonID)) 00241 { 00242 _callback = callback; 00243 } 00244 00245 bool AppLauncher::addButton(uint32_t buttonID, const char* caption) 00246 { 00247 int idx = _usedButtons++; 00248 int xspace = ((_disp->width() - ButtonColumns * ButtonWidth) / (ButtonColumns + 1)); 00249 int yspace = ((_disp->height() - TitleHeight - ButtonRows * ButtonHeight) / (ButtonRows + 1)); 00250 00251 _buttons[idx] = new Button(caption, (COLOR_T*)_fb, 00252 xspace + (ButtonWidth + xspace)*(idx%ButtonColumns), 00253 TitleHeight + yspace + (ButtonHeight + yspace)*(idx/ButtonColumns), 00254 ButtonWidth, ButtonHeight); 00255 _buttons[idx]->setAction(buttonClicked, buttonID); 00256 //_buttons[idx]->draw(); 00257 return true; 00258 } 00259 00260 bool AppLauncher::addImageButton(uint32_t buttonID, const char* imgUp, const char* imgDown) 00261 { 00262 return addImageButton(buttonID, NULL, BLACK, imgUp, imgDown); 00263 } 00264 00265 bool AppLauncher::addImageButton(uint32_t buttonID, const char* caption, COLOR_T color, const char* imgUp, const char* imgDown) 00266 { 00267 int idx = _usedButtons++; 00268 int xspace = ((_disp->width() - ButtonColumns * 128) / (ButtonColumns + 1)); 00269 int yspace = ((_disp->height() - TitleHeight - ButtonRows * 128) / (ButtonRows + 1)); 00270 int yoff = (caption == NULL) ? 0 : -15; // compensate for caption taking up space 00271 00272 ImageButton* img = new ImageButton((COLOR_T*)_fb, 00273 xspace + (128 + xspace)*(idx%ButtonColumns), 00274 TitleHeight + yspace + (128 + yspace)*(idx/ButtonColumns) + yoff, 00275 128, 128, caption, color); 00276 if (img->loadImages(imgUp, imgDown)) { 00277 _buttons[idx] = img; 00278 _buttons[idx]->setAction(buttonClicked, buttonID); 00279 //_buttons[idx]->draw(); 00280 return true; 00281 } else { 00282 //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown); 00283 return false; 00284 } 00285 } 00286 00287 bool AppLauncher::addImageButton(uint32_t buttonID, const unsigned char* imgUp, unsigned int imgUpSize, const unsigned char* imgDown, unsigned int imgDownSize) 00288 { 00289 return addImageButton(buttonID, NULL, BLACK, imgUp, imgUpSize, imgDown, imgDownSize); 00290 } 00291 00292 bool AppLauncher::addImageButton(uint32_t buttonID, const char* caption, COLOR_T color, const unsigned char* imgUp, unsigned int imgUpSize, const unsigned char* imgDown, unsigned int imgDownSize) 00293 { 00294 int idx = _usedButtons++; 00295 int xspace = ((_disp->width() - ButtonColumns * 128) / (ButtonColumns + 1)); 00296 int yspace = ((_disp->height() - TitleHeight - ButtonRows * 128) / (ButtonRows + 1)); 00297 int yoff = (caption == NULL) ? 0 : -15; // compensate for caption taking up space 00298 00299 ImageButton* img = new ImageButton((COLOR_T*)_fb, 00300 xspace + (128 + xspace)*(idx%ButtonColumns), 00301 TitleHeight + yspace + (128 + yspace)*(idx/ButtonColumns) + yoff, 00302 128, 128, caption, color); 00303 if (img->loadImages(imgUp, imgUpSize, imgDown, imgDownSize)) { 00304 _buttons[idx] = img; 00305 _buttons[idx]->setAction(buttonClicked, buttonID); 00306 //_buttons[idx]->draw(); 00307 return true; 00308 } else { 00309 //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown); 00310 return false; 00311 } 00312 }
Generated on Wed Jul 13 2022 03:01:50 by
1.7.2
