Basic swim GUI for LPC4088
Fork of DMBasicGUI by
Application/AppLauncher.cpp
- Committer:
- redbird
- Date:
- 2016-03-14
- Revision:
- 38:1b7c79a10e14
- Parent:
- 37:4a87841ebbb7
File content as of revision 38:1b7c79a10e14:
/* * Copyright 2014 Embedded Artists AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mbed.h" #include "AppLauncher.h" #include "lpc_swim_font.h" #include "Button.h" #include "ImageButton.h" #include "lpc_winfreesystem14x16.h" /****************************************************************************** * Defines and typedefs *****************************************************************************/ #define APP_PREFIX "[Launcher] " #define NO_APPLICATION (-1) #define APP_SIGID_TOUCH 0x1 /****************************************************************************** * Private variables *****************************************************************************/ static int appToLaunch = NO_APPLICATION; static osThreadId appThread; /****************************************************************************** * Private functions *****************************************************************************/ static void buttonClicked(uint32_t x) { if (appToLaunch == NO_APPLICATION) { appToLaunch = (int)x; } } void AppLauncher::draw() { // Prepare fullscreen swim_window_open(_win, _disp->width(), _disp->height(), // full size (COLOR_T*)_fb, 0,0,_disp->width()-1, _disp->height()-1, // window position and size 0, // border BLACK, WHITE, BLACK); // colors: pen, backgr, forgr swim_set_font(_win, (FONT_T*)&font_winfreesys14x16); if (_supportsCalibration) { const char* msg = "(Press physical UserButton >2s to calibrate touch)"; int w, h; swim_get_string_bounds(_win, msg, &w, &h); //swim_put_text_xy(_win, msg, (_disp->width()-w)/2, _disp->height()-h*4); } for (int i = 0; i < _usedButtons; i++) { _buttons[i]->draw(); } } void AppLauncher::onTouchEvent() { _newTouchEvent = true; osSignalSet(appThread, APP_SIGID_TOUCH); } void AppLauncher::onButtonEvent() { _newButtonEvent = true; osSignalSet(appThread, APP_SIGID_TOUCH); } static void onTimeoutEvent(void const* arg) { *((bool*)arg) = true; osSignalSet(appThread, APP_SIGID_TOUCH); } /****************************************************************************** * Public functions *****************************************************************************/ AppLauncher::AppLauncher() : _disp(NULL), _win(NULL), _fb(NULL), _usedButtons(0) { for (int i = 0; i < NumberOfButtons; i++) { _buttons[i] = NULL; } bool r; int n; if (DMBoard::instance().touchPanel()->info(&r, &n, &_supportsCalibration) != TouchPanel::TouchError_Ok) { _supportsCalibration = false; } } AppLauncher::~AppLauncher() { teardown(); } bool AppLauncher::setup() { RtosLog* log = DMBoard::instance().logger(); _disp = DMBoard::instance().display(); _win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T)); _fb = _disp->allocateFramebuffer(); if (_win == NULL || _fb == NULL) { log->printf(APP_PREFIX"Failed to allocate memory for framebuffer\r\n"); return false; } return true; } void AppLauncher::runToCompletion() { DMBoard* board = &DMBoard::instance(); RtosLog* log = board->logger(); appThread = osThreadGetId(); // Draw something on the framebuffer before using it so that it doesn't look garbled draw(); // Start display in default mode (16-bit) Display::DisplayError disperr = _disp->powerUp(_fb); if (disperr != Display::DisplayError_Ok) { log->printf(APP_PREFIX"Failed to initialize the display, got error %d\r\n", disperr); return; } // To keep track of the button pushes bool buttonPressed = false; bool buttonTimeout = false; InterruptIn button(P2_10); button.rise(this, &AppLauncher::onButtonEvent); button.fall(this, &AppLauncher::onButtonEvent); RtosTimer buttonTimer(onTimeoutEvent, osTimerOnce, &buttonTimeout); // Wait for touches TouchPanel* touch = board->touchPanel(); FunctionPointer* fpOld = touch->setListener(new FunctionPointer(this, &AppLauncher::onTouchEvent)); touch_coordinate_t coord; while (true) { Thread::signal_wait(APP_SIGID_TOUCH); if (_newTouchEvent) { if (buttonPressed) { // cancel buttonPressed = false; buttonTimer.stop(); } _newTouchEvent = false; if (touch->read(coord) != TouchPanel::TouchError_Ok) { log->printf("Failed to read touch coordinate\n"); continue; } // Process the touch coordinate for each button for (int i = 0; i < NumberOfButtons; i++) { if (_buttons[i] != NULL) { if (_buttons[i]->handle(coord.x, coord.y, coord.z > 0)) { _buttons[i]->draw(); } } } } else if (buttonTimeout) { if (board->buttonPressed()) { appToLaunch = CalibrationApp; } buttonPressed = false; buttonTimeout = false; } else if (_newButtonEvent) { _newButtonEvent = false; if (board->buttonPressed()) { buttonPressed = true; buttonTimer.start(2000); } else { buttonPressed = false; buttonTimer.stop(); } continue; } if (appToLaunch != NO_APPLICATION) { App* a = NULL; if (_callback != NULL) { a = _callback(appToLaunch); } if (a != NULL) { if (a->setup()) { a->runToCompletion(); a->teardown(); } delete a; } appToLaunch = NO_APPLICATION; } } restore old touch listener (get our listener in return) fpOld = touch->setListener(fpOld); delete fpOld; } bool AppLauncher::teardown() { if (_win != NULL) { free(_win); _win = NULL; } if (_fb != NULL) { free(_fb); _fb = NULL; } for (int i = 0; i < NumberOfButtons; i++) { _buttons[i] = NULL; if (_buttons[i] != NULL) { delete _buttons[i]; _buttons[i] = NULL; } } return true; } void AppLauncher::setAppCreatorFunc(App*(*callback)(uint32_t buttonID)) { _callback = callback; } bool AppLauncher::addButton(uint32_t buttonID, const char* caption) { int idx = _usedButtons++; int xspace = ((_disp->width() - ButtonColumns * ButtonWidth) / (ButtonColumns + 1)); int yspace = ((_disp->height() - TitleHeight - ButtonRows * ButtonHeight) / (ButtonRows + 1)); _buttons[idx] = new Button(caption, (COLOR_T*)_fb, xspace + (ButtonWidth + xspace)*(idx%ButtonColumns), TitleHeight + yspace + (ButtonHeight + yspace)*(idx/ButtonColumns), ButtonWidth, ButtonHeight); _buttons[idx]->setAction(buttonClicked, buttonID); //_buttons[idx]->draw(); return true; } bool AppLauncher::addImageButton(uint32_t buttonID, const char* imgUp, const char* imgDown) { return addImageButton(buttonID, NULL, BLACK, imgUp, imgDown); } bool AppLauncher::addImageButton(uint32_t buttonID, const char* caption, COLOR_T color, const char* imgUp, const char* imgDown) { int idx = _usedButtons++; int xspace = ((_disp->width() - ButtonColumns * 128) / (ButtonColumns + 1)); int yspace = ((_disp->height() - TitleHeight - ButtonRows * 128) / (ButtonRows + 1)); int yoff = (caption == NULL) ? 0 : -15; // compensate for caption taking up space ImageButton* img = new ImageButton((COLOR_T*)_fb, xspace + (128 + xspace)*(idx%ButtonColumns), TitleHeight + yspace + (128 + yspace)*(idx/ButtonColumns) + yoff, 128, 128, caption, color); if (img->loadImages(imgUp, imgDown)) { _buttons[idx] = img; _buttons[idx]->setAction(buttonClicked, buttonID); //_buttons[idx]->draw(); return true; } else { //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown); return false; } } bool AppLauncher::addImageButton(uint32_t buttonID, const unsigned char* imgUp, unsigned int imgUpSize, const unsigned char* imgDown, unsigned int imgDownSize) { return addImageButton(buttonID, NULL, BLACK, imgUp, imgUpSize, imgDown, imgDownSize); } 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) { int idx = _usedButtons++; int xspace = ((_disp->width() - ButtonColumns * 128) / (ButtonColumns + 1)); int yspace = ((_disp->height() - TitleHeight - ButtonRows * 128) / (ButtonRows + 1)); int yoff = (caption == NULL) ? 0 : -15; // compensate for caption taking up space ImageButton* img = new ImageButton((COLOR_T*)_fb, xspace + (128 + xspace)*(idx%ButtonColumns), TitleHeight + yspace + (128 + yspace)*(idx/ButtonColumns) + yoff, 128, 128, caption, color); if (img->loadImages(imgUp, imgUpSize, imgDown, imgDownSize)) { _buttons[idx] = img; _buttons[idx]->setAction(buttonClicked, buttonID); //_buttons[idx]->draw(); return true; } else { //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown); return false; } }