A basic graphics package for the LPC4088 Display Module.

Dependents:   lpc4088_displaymodule_demo_sphere sampleGUI sampleEmptyGUI lpc4088_displaymodule_fs_aid ... more

Fork of DMBasicGUI by EmbeddedArtists AB

Committer:
embeddedartists
Date:
Mon Nov 04 14:31:50 2019 +0000
Revision:
22:f0d00f29bfeb
Parent:
21:0038059e3a8f
More updates related to mbed OS 5

Who changed what in which revision?

UserRevisionLine numberNew contents of line
embeddedartists 0:4977187e90c7 1 /*
embeddedartists 0:4977187e90c7 2 * Copyright 2014 Embedded Artists AB
embeddedartists 0:4977187e90c7 3 *
embeddedartists 0:4977187e90c7 4 * Licensed under the Apache License, Version 2.0 (the "License");
embeddedartists 0:4977187e90c7 5 * you may not use this file except in compliance with the License.
embeddedartists 0:4977187e90c7 6 * You may obtain a copy of the License at
embeddedartists 0:4977187e90c7 7 *
embeddedartists 0:4977187e90c7 8 * http://www.apache.org/licenses/LICENSE-2.0
embeddedartists 0:4977187e90c7 9 *
embeddedartists 0:4977187e90c7 10 * Unless required by applicable law or agreed to in writing, software
embeddedartists 0:4977187e90c7 11 * distributed under the License is distributed on an "AS IS" BASIS,
embeddedartists 0:4977187e90c7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
embeddedartists 0:4977187e90c7 13 * See the License for the specific language governing permissions and
embeddedartists 0:4977187e90c7 14 * limitations under the License.
embeddedartists 0:4977187e90c7 15 */
embeddedartists 0:4977187e90c7 16
embeddedartists 0:4977187e90c7 17
embeddedartists 0:4977187e90c7 18 #include "mbed.h"
embeddedartists 0:4977187e90c7 19 #include "AppLauncher.h"
embeddedartists 0:4977187e90c7 20 #include "lpc_swim_font.h"
embeddedartists 0:4977187e90c7 21 #include "Button.h"
embeddedartists 3:3fabfe3339b8 22 #include "ImageButton.h"
embeddedartists 0:4977187e90c7 23
embeddedartists 0:4977187e90c7 24 /******************************************************************************
embeddedartists 0:4977187e90c7 25 * Defines and typedefs
embeddedartists 0:4977187e90c7 26 *****************************************************************************/
embeddedartists 0:4977187e90c7 27
embeddedartists 0:4977187e90c7 28 #define APP_PREFIX "[Launcher] "
embeddedartists 0:4977187e90c7 29
embeddedartists 5:f4de114c31c3 30 #define NO_APPLICATION (-1)
embeddedartists 0:4977187e90c7 31
embeddedartists 8:19a6b70d42b1 32 #define APP_SIGID_TOUCH 0x1
embeddedartists 0:4977187e90c7 33
embeddedartists 0:4977187e90c7 34 /******************************************************************************
embeddedartists 0:4977187e90c7 35 * Private variables
embeddedartists 0:4977187e90c7 36 *****************************************************************************/
embeddedartists 0:4977187e90c7 37
embeddedartists 5:f4de114c31c3 38 static int appToLaunch = NO_APPLICATION;
embeddedartists 8:19a6b70d42b1 39 static osThreadId appThread;
embeddedartists 0:4977187e90c7 40
embeddedartists 0:4977187e90c7 41 /******************************************************************************
embeddedartists 0:4977187e90c7 42 * Private functions
embeddedartists 0:4977187e90c7 43 *****************************************************************************/
embeddedartists 0:4977187e90c7 44
embeddedartists 0:4977187e90c7 45 static void buttonClicked(uint32_t x)
embeddedartists 0:4977187e90c7 46 {
embeddedartists 5:f4de114c31c3 47 if (appToLaunch == NO_APPLICATION) {
embeddedartists 5:f4de114c31c3 48 appToLaunch = (int)x;
embeddedartists 0:4977187e90c7 49 }
embeddedartists 0:4977187e90c7 50 }
embeddedartists 0:4977187e90c7 51
embeddedartists 0:4977187e90c7 52 void AppLauncher::draw()
embeddedartists 0:4977187e90c7 53 {
embeddedartists 0:4977187e90c7 54 // Prepare fullscreen
embeddedartists 0:4977187e90c7 55 swim_window_open(_win,
embeddedartists 0:4977187e90c7 56 _disp->width(), _disp->height(), // full size
embeddedartists 0:4977187e90c7 57 (COLOR_T*)_fb,
embeddedartists 0:4977187e90c7 58 0,0,_disp->width()-1, _disp->height()-1, // window position and size
embeddedartists 0:4977187e90c7 59 1, // border
embeddedartists 3:3fabfe3339b8 60 WHITE, BLACK, BLACK); // colors: pen, backgr, forgr
embeddedartists 0:4977187e90c7 61 swim_set_title(_win, "Demo Program", BLACK);
embeddedartists 0:4977187e90c7 62
embeddedartists 8:19a6b70d42b1 63 if (_supportsCalibration) {
embeddedartists 8:19a6b70d42b1 64 const char* msg = "(Press physical UserButton >2s to calibrate touch)";
embeddedartists 8:19a6b70d42b1 65 int w, h;
embeddedartists 8:19a6b70d42b1 66 swim_get_string_bounds(_win, msg, &w, &h);
embeddedartists 8:19a6b70d42b1 67 swim_put_text_xy(_win, msg, (_disp->width()-w)/2, _disp->height()-h*4);
embeddedartists 8:19a6b70d42b1 68 }
embeddedartists 5:f4de114c31c3 69
embeddedartists 5:f4de114c31c3 70 for (int i = 0; i < _usedButtons; i++) {
embeddedartists 5:f4de114c31c3 71 _buttons[i]->draw();
embeddedartists 5:f4de114c31c3 72 }
embeddedartists 0:4977187e90c7 73 }
embeddedartists 0:4977187e90c7 74
embeddedartists 8:19a6b70d42b1 75 void AppLauncher::onTouchEvent()
embeddedartists 8:19a6b70d42b1 76 {
embeddedartists 8:19a6b70d42b1 77 _newTouchEvent = true;
embeddedartists 8:19a6b70d42b1 78 osSignalSet(appThread, APP_SIGID_TOUCH);
embeddedartists 8:19a6b70d42b1 79 }
embeddedartists 8:19a6b70d42b1 80
embeddedartists 8:19a6b70d42b1 81 void AppLauncher::onButtonEvent()
embeddedartists 8:19a6b70d42b1 82 {
embeddedartists 8:19a6b70d42b1 83 _newButtonEvent = true;
embeddedartists 8:19a6b70d42b1 84 osSignalSet(appThread, APP_SIGID_TOUCH);
embeddedartists 8:19a6b70d42b1 85 }
embeddedartists 8:19a6b70d42b1 86
embeddedartists 11:265884fa7fdd 87 static void onTimeoutEvent(void const* arg)
embeddedartists 8:19a6b70d42b1 88 {
embeddedartists 8:19a6b70d42b1 89 *((bool*)arg) = true;
embeddedartists 8:19a6b70d42b1 90 osSignalSet(appThread, APP_SIGID_TOUCH);
embeddedartists 8:19a6b70d42b1 91 }
embeddedartists 8:19a6b70d42b1 92
embeddedartists 0:4977187e90c7 93 /******************************************************************************
embeddedartists 0:4977187e90c7 94 * Public functions
embeddedartists 0:4977187e90c7 95 *****************************************************************************/
embeddedartists 0:4977187e90c7 96
embeddedartists 0:4977187e90c7 97 AppLauncher::AppLauncher() : _disp(NULL), _win(NULL), _fb(NULL), _usedButtons(0)
embeddedartists 0:4977187e90c7 98 {
embeddedartists 0:4977187e90c7 99 for (int i = 0; i < NumberOfButtons; i++) {
embeddedartists 0:4977187e90c7 100 _buttons[i] = NULL;
embeddedartists 0:4977187e90c7 101 }
embeddedartists 8:19a6b70d42b1 102 bool r;
embeddedartists 8:19a6b70d42b1 103 int n;
embeddedartists 8:19a6b70d42b1 104 if (DMBoard::instance().touchPanel()->info(&r, &n, &_supportsCalibration) != TouchPanel::TouchError_Ok) {
embeddedartists 8:19a6b70d42b1 105 _supportsCalibration = false;
embeddedartists 8:19a6b70d42b1 106 }
embeddedartists 0:4977187e90c7 107 }
embeddedartists 0:4977187e90c7 108
embeddedartists 0:4977187e90c7 109 AppLauncher::~AppLauncher()
embeddedartists 0:4977187e90c7 110 {
embeddedartists 0:4977187e90c7 111 teardown();
embeddedartists 0:4977187e90c7 112 }
embeddedartists 0:4977187e90c7 113
embeddedartists 0:4977187e90c7 114 bool AppLauncher::setup()
embeddedartists 0:4977187e90c7 115 {
embeddedartists 0:4977187e90c7 116 RtosLog* log = DMBoard::instance().logger();
embeddedartists 0:4977187e90c7 117
embeddedartists 0:4977187e90c7 118 _disp = DMBoard::instance().display();
embeddedartists 0:4977187e90c7 119 _win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T));
embeddedartists 0:4977187e90c7 120 _fb = _disp->allocateFramebuffer();
embeddedartists 0:4977187e90c7 121
embeddedartists 0:4977187e90c7 122 if (_win == NULL || _fb == NULL) {
embeddedartists 0:4977187e90c7 123 log->printf(APP_PREFIX"Failed to allocate memory for framebuffer\r\n");
embeddedartists 0:4977187e90c7 124 return false;
embeddedartists 0:4977187e90c7 125 }
embeddedartists 0:4977187e90c7 126
embeddedartists 0:4977187e90c7 127 return true;
embeddedartists 0:4977187e90c7 128 }
embeddedartists 0:4977187e90c7 129
embeddedartists 0:4977187e90c7 130 void AppLauncher::runToCompletion()
embeddedartists 0:4977187e90c7 131 {
embeddedartists 0:4977187e90c7 132 DMBoard* board = &DMBoard::instance();
embeddedartists 0:4977187e90c7 133 RtosLog* log = board->logger();
embeddedartists 8:19a6b70d42b1 134
embeddedartists 8:19a6b70d42b1 135 appThread = osThreadGetId();
embeddedartists 0:4977187e90c7 136
embeddedartists 0:4977187e90c7 137 // Draw something on the framebuffer before using it so that it doesn't look garbled
embeddedartists 0:4977187e90c7 138 draw();
embeddedartists 0:4977187e90c7 139
embeddedartists 0:4977187e90c7 140 // Start display in default mode (16-bit)
embeddedartists 0:4977187e90c7 141 Display::DisplayError disperr = _disp->powerUp(_fb);
embeddedartists 3:3fabfe3339b8 142 if (disperr != Display::DisplayError_Ok) {
embeddedartists 0:4977187e90c7 143 log->printf(APP_PREFIX"Failed to initialize the display, got error %d\r\n", disperr);
embeddedartists 0:4977187e90c7 144 return;
embeddedartists 0:4977187e90c7 145 }
embeddedartists 8:19a6b70d42b1 146
embeddedartists 0:4977187e90c7 147 // To keep track of the button pushes
embeddedartists 0:4977187e90c7 148 bool buttonPressed = false;
embeddedartists 8:19a6b70d42b1 149 bool buttonTimeout = false;
embeddedartists 12:53601973f7eb 150 InterruptIn button(P2_10);
embeddedartists 21:0038059e3a8f 151 button.rise(callback(this, &AppLauncher::onButtonEvent));
embeddedartists 21:0038059e3a8f 152 button.fall(callback(this, &AppLauncher::onButtonEvent));
embeddedartists 21:0038059e3a8f 153 //RtosTimer buttonTimer(onTimeoutEvent, osTimerOnce, &buttonTimeout);
embeddedartists 21:0038059e3a8f 154 EventQueue buttonTimer(4*EVENTS_EVENT_SIZE);
embeddedartists 21:0038059e3a8f 155 int buttonTimerId = buttonTimer.call_in(2000, onTimeoutEvent, &buttonTimeout);
embeddedartists 0:4977187e90c7 156
embeddedartists 0:4977187e90c7 157 // Wait for touches
embeddedartists 0:4977187e90c7 158 TouchPanel* touch = board->touchPanel();
embeddedartists 21:0038059e3a8f 159 //FunctionPointer* fpOld = touch->setListener(new FunctionPointer(this, &AppLauncher::onTouchEvent));
embeddedartists 21:0038059e3a8f 160 touch->setListener(callback(this, &AppLauncher::onTouchEvent));
embeddedartists 8:19a6b70d42b1 161 touch_coordinate_t coord;
embeddedartists 8:19a6b70d42b1 162 while (true) {
embeddedartists 21:0038059e3a8f 163 ThisThread::flags_wait_any(APP_SIGID_TOUCH);
embeddedartists 8:19a6b70d42b1 164 if (_newTouchEvent) {
embeddedartists 8:19a6b70d42b1 165 if (buttonPressed) {
embeddedartists 8:19a6b70d42b1 166 // cancel
embeddedartists 8:19a6b70d42b1 167 buttonPressed = false;
embeddedartists 21:0038059e3a8f 168 //buttonTimer.stop();
embeddedartists 21:0038059e3a8f 169 buttonTimer.cancel(buttonTimerId);
embeddedartists 8:19a6b70d42b1 170 }
embeddedartists 8:19a6b70d42b1 171 _newTouchEvent = false;
embeddedartists 8:19a6b70d42b1 172 if (touch->read(coord) != TouchPanel::TouchError_Ok) {
embeddedartists 8:19a6b70d42b1 173 log->printf("Failed to read touch coordinate\n");
embeddedartists 8:19a6b70d42b1 174 continue;
embeddedartists 8:19a6b70d42b1 175 }
embeddedartists 8:19a6b70d42b1 176 // Process the touch coordinate for each button
embeddedartists 8:19a6b70d42b1 177 for (int i = 0; i < NumberOfButtons; i++) {
embeddedartists 0:4977187e90c7 178 if (_buttons[i] != NULL) {
embeddedartists 8:19a6b70d42b1 179 if (_buttons[i]->handle(coord.x, coord.y, coord.z > 0)) {
embeddedartists 8:19a6b70d42b1 180 _buttons[i]->draw();
embeddedartists 8:19a6b70d42b1 181 }
embeddedartists 0:4977187e90c7 182 }
embeddedartists 8:19a6b70d42b1 183 }
embeddedartists 8:19a6b70d42b1 184 } else if (buttonTimeout) {
embeddedartists 8:19a6b70d42b1 185 if (board->buttonPressed()) {
embeddedartists 8:19a6b70d42b1 186 appToLaunch = CalibrationApp;
embeddedartists 8:19a6b70d42b1 187 }
embeddedartists 8:19a6b70d42b1 188 buttonPressed = false;
embeddedartists 8:19a6b70d42b1 189 buttonTimeout = false;
embeddedartists 8:19a6b70d42b1 190 } else if (_newButtonEvent) {
embeddedartists 8:19a6b70d42b1 191 _newButtonEvent = false;
embeddedartists 8:19a6b70d42b1 192 if (board->buttonPressed()) {
embeddedartists 8:19a6b70d42b1 193 buttonPressed = true;
embeddedartists 21:0038059e3a8f 194 //buttonTimer.start(2000);
embeddedartists 21:0038059e3a8f 195 buttonTimer.dispatch(0);
embeddedartists 8:19a6b70d42b1 196 } else {
embeddedartists 8:19a6b70d42b1 197 buttonPressed = false;
embeddedartists 21:0038059e3a8f 198 //buttonTimer.stop();
embeddedartists 21:0038059e3a8f 199 buttonTimer.cancel(buttonTimerId);
embeddedartists 8:19a6b70d42b1 200 }
embeddedartists 8:19a6b70d42b1 201 continue;
embeddedartists 0:4977187e90c7 202 }
embeddedartists 0:4977187e90c7 203
embeddedartists 5:f4de114c31c3 204 if (appToLaunch != NO_APPLICATION) {
embeddedartists 0:4977187e90c7 205 App* a = NULL;
embeddedartists 5:f4de114c31c3 206 if (_callback != NULL) {
embeddedartists 5:f4de114c31c3 207 a = _callback(appToLaunch);
embeddedartists 0:4977187e90c7 208 }
embeddedartists 0:4977187e90c7 209 if (a != NULL) {
embeddedartists 0:4977187e90c7 210 if (a->setup()) {
embeddedartists 0:4977187e90c7 211 a->runToCompletion();
embeddedartists 0:4977187e90c7 212 a->teardown();
embeddedartists 0:4977187e90c7 213 }
embeddedartists 0:4977187e90c7 214 delete a;
embeddedartists 0:4977187e90c7 215 }
embeddedartists 5:f4de114c31c3 216 appToLaunch = NO_APPLICATION;
embeddedartists 5:f4de114c31c3 217 }
embeddedartists 0:4977187e90c7 218 }
embeddedartists 8:19a6b70d42b1 219
embeddedartists 8:19a6b70d42b1 220 // restore old touch listener (get our listener in return)
embeddedartists 11:265884fa7fdd 221 //fpOld = touch->setListener(fpOld);
embeddedartists 11:265884fa7fdd 222 //delete fpOld;
embeddedartists 0:4977187e90c7 223 }
embeddedartists 0:4977187e90c7 224
embeddedartists 0:4977187e90c7 225 bool AppLauncher::teardown()
embeddedartists 0:4977187e90c7 226 {
embeddedartists 0:4977187e90c7 227 if (_win != NULL) {
embeddedartists 0:4977187e90c7 228 free(_win);
embeddedartists 0:4977187e90c7 229 _win = NULL;
embeddedartists 0:4977187e90c7 230 }
embeddedartists 0:4977187e90c7 231 if (_fb != NULL) {
embeddedartists 0:4977187e90c7 232 free(_fb);
embeddedartists 0:4977187e90c7 233 _fb = NULL;
embeddedartists 0:4977187e90c7 234 }
embeddedartists 0:4977187e90c7 235 for (int i = 0; i < NumberOfButtons; i++) {
embeddedartists 0:4977187e90c7 236 _buttons[i] = NULL;
embeddedartists 0:4977187e90c7 237 if (_buttons[i] != NULL) {
embeddedartists 0:4977187e90c7 238 delete _buttons[i];
embeddedartists 0:4977187e90c7 239 _buttons[i] = NULL;
embeddedartists 0:4977187e90c7 240 }
embeddedartists 0:4977187e90c7 241 }
embeddedartists 0:4977187e90c7 242 return true;
embeddedartists 0:4977187e90c7 243 }
embeddedartists 0:4977187e90c7 244
embeddedartists 5:f4de114c31c3 245 void AppLauncher::setAppCreatorFunc(App*(*callback)(uint32_t buttonID))
embeddedartists 5:f4de114c31c3 246 {
embeddedartists 5:f4de114c31c3 247 _callback = callback;
embeddedartists 5:f4de114c31c3 248 }
embeddedartists 0:4977187e90c7 249
embeddedartists 5:f4de114c31c3 250 bool AppLauncher::addButton(uint32_t buttonID, const char* caption)
embeddedartists 5:f4de114c31c3 251 {
embeddedartists 5:f4de114c31c3 252 int idx = _usedButtons++;
embeddedartists 5:f4de114c31c3 253 int xspace = ((_disp->width() - ButtonColumns * ButtonWidth) / (ButtonColumns + 1));
embeddedartists 5:f4de114c31c3 254 int yspace = ((_disp->height() - TitleHeight - ButtonRows * ButtonHeight) / (ButtonRows + 1));
embeddedartists 5:f4de114c31c3 255
embeddedartists 5:f4de114c31c3 256 _buttons[idx] = new Button(caption, (COLOR_T*)_fb,
embeddedartists 5:f4de114c31c3 257 xspace + (ButtonWidth + xspace)*(idx%ButtonColumns),
embeddedartists 5:f4de114c31c3 258 TitleHeight + yspace + (ButtonHeight + yspace)*(idx/ButtonColumns),
embeddedartists 5:f4de114c31c3 259 ButtonWidth, ButtonHeight);
embeddedartists 5:f4de114c31c3 260 _buttons[idx]->setAction(buttonClicked, buttonID);
embeddedartists 5:f4de114c31c3 261 //_buttons[idx]->draw();
embeddedartists 5:f4de114c31c3 262 return true;
embeddedartists 5:f4de114c31c3 263 }
embeddedartists 5:f4de114c31c3 264
embeddedartists 5:f4de114c31c3 265 bool AppLauncher::addImageButton(uint32_t buttonID, const char* imgUp, const char* imgDown)
embeddedartists 5:f4de114c31c3 266 {
embeddedartists 11:265884fa7fdd 267 return addImageButton(buttonID, NULL, BLACK, imgUp, imgDown);
embeddedartists 11:265884fa7fdd 268 }
embeddedartists 11:265884fa7fdd 269
embeddedartists 11:265884fa7fdd 270 bool AppLauncher::addImageButton(uint32_t buttonID, const char* caption, COLOR_T color, const char* imgUp, const char* imgDown)
embeddedartists 11:265884fa7fdd 271 {
embeddedartists 5:f4de114c31c3 272 int idx = _usedButtons++;
embeddedartists 5:f4de114c31c3 273 int xspace = ((_disp->width() - ButtonColumns * 64) / (ButtonColumns + 1));
embeddedartists 5:f4de114c31c3 274 int yspace = ((_disp->height() - TitleHeight - ButtonRows * 64) / (ButtonRows + 1));
embeddedartists 11:265884fa7fdd 275 int yoff = (caption == NULL) ? 0 : -15; // compensate for caption taking up space
embeddedartists 5:f4de114c31c3 276
embeddedartists 5:f4de114c31c3 277 ImageButton* img = new ImageButton((COLOR_T*)_fb,
embeddedartists 5:f4de114c31c3 278 xspace + (64 + xspace)*(idx%ButtonColumns),
embeddedartists 11:265884fa7fdd 279 TitleHeight + yspace + (64 + yspace)*(idx/ButtonColumns) + yoff,
embeddedartists 11:265884fa7fdd 280 64, 64, caption, color);
embeddedartists 5:f4de114c31c3 281 if (img->loadImages(imgUp, imgDown)) {
embeddedartists 5:f4de114c31c3 282 _buttons[idx] = img;
embeddedartists 5:f4de114c31c3 283 _buttons[idx]->setAction(buttonClicked, buttonID);
embeddedartists 5:f4de114c31c3 284 //_buttons[idx]->draw();
embeddedartists 5:f4de114c31c3 285 return true;
embeddedartists 5:f4de114c31c3 286 } else {
embeddedartists 5:f4de114c31c3 287 //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown);
embeddedartists 5:f4de114c31c3 288 return false;
embeddedartists 5:f4de114c31c3 289 }
embeddedartists 5:f4de114c31c3 290 }
embeddedartists 5:f4de114c31c3 291
embeddedartists 5:f4de114c31c3 292 bool AppLauncher::addImageButton(uint32_t buttonID, const unsigned char* imgUp, unsigned int imgUpSize, const unsigned char* imgDown, unsigned int imgDownSize)
embeddedartists 5:f4de114c31c3 293 {
embeddedartists 11:265884fa7fdd 294 return addImageButton(buttonID, NULL, BLACK, imgUp, imgUpSize, imgDown, imgDownSize);
embeddedartists 11:265884fa7fdd 295 }
embeddedartists 11:265884fa7fdd 296
embeddedartists 11:265884fa7fdd 297 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)
embeddedartists 11:265884fa7fdd 298 {
embeddedartists 5:f4de114c31c3 299 int idx = _usedButtons++;
embeddedartists 5:f4de114c31c3 300 int xspace = ((_disp->width() - ButtonColumns * 64) / (ButtonColumns + 1));
embeddedartists 5:f4de114c31c3 301 int yspace = ((_disp->height() - TitleHeight - ButtonRows * 64) / (ButtonRows + 1));
embeddedartists 11:265884fa7fdd 302 int yoff = (caption == NULL) ? 0 : -15; // compensate for caption taking up space
embeddedartists 5:f4de114c31c3 303
embeddedartists 5:f4de114c31c3 304 ImageButton* img = new ImageButton((COLOR_T*)_fb,
embeddedartists 5:f4de114c31c3 305 xspace + (64 + xspace)*(idx%ButtonColumns),
embeddedartists 11:265884fa7fdd 306 TitleHeight + yspace + (64 + yspace)*(idx/ButtonColumns) + yoff,
embeddedartists 11:265884fa7fdd 307 64, 64, caption, color);
embeddedartists 5:f4de114c31c3 308 if (img->loadImages(imgUp, imgUpSize, imgDown, imgDownSize)) {
embeddedartists 5:f4de114c31c3 309 _buttons[idx] = img;
embeddedartists 5:f4de114c31c3 310 _buttons[idx]->setAction(buttonClicked, buttonID);
embeddedartists 5:f4de114c31c3 311 //_buttons[idx]->draw();
embeddedartists 5:f4de114c31c3 312 return true;
embeddedartists 5:f4de114c31c3 313 } else {
embeddedartists 5:f4de114c31c3 314 //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown);
embeddedartists 5:f4de114c31c3 315 return false;
embeddedartists 5:f4de114c31c3 316 }
embeddedartists 5:f4de114c31c3 317 }