📄 ctk.c
字号:
/** * \file * The Contiki Toolkit CTK, the Contiki GUI. * \author Adam Dunkels <adam@dunkels.com> * * The Contiki Toolkit (CTK) provides the graphical user interface for * the Contiki system. * * * * *//* * Copyright (c) 2002-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This file is part of the "ctk" console GUI toolkit for cc65 * * $Id: ctk.c,v 1.33 2003/09/04 19:36:04 adamdunkels Exp $ * */#include "cc.h"#include "ek.h"#include "dispatcher.h"#include "ctk.h"#include "ctk-draw.h"#include "ctk-conf.h"#include "ctk-mouse.h"#include <string.h>static unsigned char height, width;static unsigned char mode;static struct ctk_window desktop_window;static struct ctk_window *windows;static struct ctk_window *dialog;#if CTK_CONF_MENUSstatic struct ctk_menus menus;static struct ctk_menu *lastmenu;static struct ctk_menu desktopmenu;#endif /* CTK_CONF_MENUS */#ifndef NULL#define NULL (void *)0#endif /* NULL */#define REDRAW_NONE 0#define REDRAW_ALL 1#define REDRAW_FOCUS 2#define REDRAW_WIDGETS 4#define REDRAW_MENUS 8#define REDRAW_MENUPART 16#define MAX_REDRAWWIDGETS 4static unsigned char redraw;static struct ctk_widget *redraw_widgets[MAX_REDRAWWIDGETS];static unsigned char redraw_widgetptr;static unsigned char maxnitems;static unsigned char iconx, icony;#define ICONX_START (width - 6)#define ICONY_START 0#define ICONX_DELTA -16#define ICONY_DELTA 5#define ICONY_MAX (height - 5)static void ctk_idle(void);static struct dispatcher_proc p = {DISPATCHER_PROC("CTK Contiki GUI", ctk_idle, NULL, NULL)};static ek_id_t ctkid;ek_signal_t /** Emitted for every key being pressed. The key is passed as signal data.*/ ctk_signal_keypress, /** Emitted when a widget is activated (pressed). A pointer to the widget is passed as signal data. */ ctk_signal_widget_activate, /** \deprecated Same as ctk_signal_widget_activate. */ ctk_signal_button_activate, /** Emitted when a widget is selected. A pointer to the widget is passed as signal data. */ ctk_signal_widget_select, /** \deprecated Same as ctk_signal_widget_select. */ ctk_signal_button_hover, /** Emitted when a hyperlink is activated. The signal is broadcast to all listeners. */ ctk_signal_hyperlink_activate, /** \deprecated Same as ctk_signal_widget_select.. */ ctk_signal_hyperlink_hover, /** Emitted when a menu item is activated. The number of the menu item is passed as signal data. */ ctk_signal_menu_activate, /** Emitted when a window is closed. A pointer to the window is passed as signal data. */ ctk_signal_window_close, /** Emitted when the mouse pointer is moved. A NULL pointer is passed as signal data and it is up to the listening process to check the position of the mouse using the CTK mouse API.*/ ctk_signal_pointer_move, /** Emitted when a mouse button is pressed. The button is passed as signal data to the listening process. */ ctk_signal_pointer_button;#if CTK_CONF_SCREENSAVERek_signal_t ctk_signal_screensaver_stop, ctk_signal_screensaver_start;#endif /* CTK_CONF_SCREENSAVER */#if CTK_CONF_MOUSE_SUPPORTunsigned short mouse_x, mouse_y, mouse_button;#endif /* CTK_CONF_MOUSE_SUPPORT */static unsigned short screensaver_timer = 0;unsigned short ctk_screensaver_timeout = (5*60);static ek_clock_t start, current;#if CTK_CONF_MENUS/*-----------------------------------------------------------------------------------*//** * \internal Creates the Desktop menu. * * Creates the leftmost menu, "Desktop". Since the desktop menu * contains the list of all open windows, this function will be called * whenever a window is opened or closed. *//*-----------------------------------------------------------------------------------*/static voidmake_desktopmenu(void){ struct ctk_window *w; desktopmenu.nitems = 0; if(windows == NULL) { ctk_menuitem_add(&desktopmenu, "(No windows)"); } else { for(w = windows; w != NULL; w = w->next) { ctk_menuitem_add(&desktopmenu, w->title); } }}#endif /* CTK_CONF_MENUS *//*-----------------------------------------------------------------------------------*//** * Initializes the Contiki Toolkit. * * This function must be called before any other CTK function, but * after the inizialitation of the dispatcher module. *//*-----------------------------------------------------------------------------------*/voidctk_init(void){ ctkid = dispatcher_start(&p); windows = NULL; dialog = NULL;#if CTK_CONF_MENUS ctk_menu_new(&desktopmenu, "Desktop"); make_desktopmenu(); menus.menus = menus.desktopmenu = &desktopmenu;#endif /* CTK_CONF_MENUS */#if CTK_CONF_MOUSE_SUPPORT ctk_mouse_init(); ctk_mouse_show();#endif /* CTK_CONF_MOUSE_SUPPORT */ ctk_draw_init(); height = ctk_draw_height(); width = ctk_draw_width(); desktop_window.active = NULL; ctk_signal_keypress = dispatcher_sigalloc(); ctk_signal_button_activate = ctk_signal_widget_activate = dispatcher_sigalloc(); ctk_signal_button_hover = ctk_signal_hyperlink_hover = ctk_signal_widget_select = dispatcher_sigalloc(); ctk_signal_hyperlink_activate = dispatcher_sigalloc(); ctk_signal_menu_activate = dispatcher_sigalloc(); ctk_signal_window_close = dispatcher_sigalloc(); ctk_signal_pointer_move = dispatcher_sigalloc(); ctk_signal_pointer_button = dispatcher_sigalloc();#if CTK_CONF_SCREENSAVER ctk_signal_screensaver_start = dispatcher_sigalloc(); ctk_signal_screensaver_stop = dispatcher_sigalloc();#endif /* CTK_CONF_SCREENSAVER */ mode = CTK_MODE_NORMAL; iconx = ICONX_START; icony = ICONY_START; redraw = REDRAW_ALL; start = ek_clock();}/*-----------------------------------------------------------------------------------*//** * Sets the current CTK mode. * * The CTK mode can be either CTK_MODE_NORMAL, CTK_MODE_SCREENSAVER or * CTK_MODE_EXTERNAL. CTK_MODE_NORMAL is the normal mode, in which * keypresses and mouse pointer movements are processed and the screen * is redrawn. In CTK_MODE_SCREENSAVER, no screen redraws are * performed and the first key press or pointer movement will cause * the ctk_signal_screensaver_stop to be emitted. In the * CTK_MODE_EXTERNAL mode, key presses and pointer movements are * ignored and no screen redraws are made. * * \param m The mode. *//*-----------------------------------------------------------------------------------*/voidctk_mode_set(unsigned char m) { mode = m;}/*-----------------------------------------------------------------------------------*//** * Retrieves the current CTK mode. * * \return The current CTK mode. *//*-----------------------------------------------------------------------------------*/unsigned charctk_mode_get(void) { return mode;}/*-----------------------------------------------------------------------------------*//** * Add an icon to the desktop. * * \param icon The icon to be added. * * \param id The process ID of the process that owns the icon. *//*-----------------------------------------------------------------------------------*/voidctk_icon_add(CC_REGISTER_ARG struct ctk_widget *icon, ek_id_t id){#if CTK_CONF_ICONS icon->x = iconx; icon->y = icony; icon->widget.icon.owner = id; icony += ICONY_DELTA; if(icony >= ICONY_MAX) { icony = ICONY_START; iconx += ICONX_DELTA; } ctk_widget_add(&desktop_window, icon);#endif /* CTK_CONF_ICONS */}/*-----------------------------------------------------------------------------------*//** * Open a dialog box. * * \param d The dialog to be opened. *//*-----------------------------------------------------------------------------------*/voidctk_dialog_open(struct ctk_window *d){ dialog = d; redraw |= REDRAW_FOCUS;} /*-----------------------------------------------------------------------------------*//** * Close the dialog box, if one is open. * *//*-----------------------------------------------------------------------------------*/voidctk_dialog_close(void){ dialog = NULL; redraw |= REDRAW_ALL;}/*-----------------------------------------------------------------------------------*//** * Open a window, or bring window to front if already open. * * \param w The window to be opened. *//*-----------------------------------------------------------------------------------*/voidctk_window_open(CC_REGISTER_ARG struct ctk_window *w){ struct ctk_window *w2; /* Check if already open. */ for(w2 = windows; w2 != w && w2 != NULL; w2 = w2->next); if(w2 == NULL) { /* Not open, so we add it at the head of the list of open windows. */ w->next = windows; if(windows != NULL) { windows->prev = w; } windows = w; w->prev = NULL; } else { /* Window already open, so we move it to the front of the windows list. */ if(w != windows) { if(w->next != NULL) { w->next->prev = w->prev; } if(w->prev != NULL) { w->prev->next = w->next; } w->next = windows; windows->prev = w; windows = w; w->prev = NULL; } } #if CTK_CONF_MENUS /* Recreate the Desktop menu's window entries.*/ make_desktopmenu();#endif /* CTK_CONF_MENUS */ redraw |= REDRAW_ALL;}/*-----------------------------------------------------------------------------------*//** * Close a window if it is open. * * If the window is not open, this function does nothing. * * \param w The window to be closed. *//*-----------------------------------------------------------------------------------*/voidctk_window_close(struct ctk_window *w){ static struct ctk_window *w2; if(w == NULL) { return; } /* Check if the window to be closed is the first window on the list. */ if(w == windows) { windows = w->next; if(windows != NULL) { windows->prev = NULL; } w->next = w->prev = NULL; } else { /* Otherwise we step through the list until we find the window before the one to be closed. We then redirect its ->next pointer and its ->next->prev. */ for(w2 = windows; w2 != NULL && w2->next != w; w2 = w2->next); if(w2 == NULL) { /* The window wasn't open, so there is nothing more for us to do. */ return; } if(w->next != NULL) { w->next->prev = w->prev; } w2->next = w->next; w->next = w->prev = NULL; } #if CTK_CONF_MENUS /* Recreate the Desktop menu's window entries.*/ make_desktopmenu();#endif /* CTK_CONF_MENUS */ redraw |= REDRAW_ALL;}/*-----------------------------------------------------------------------------------*//** * \internal Create the move and close buttons on the window titlebar. *//*-----------------------------------------------------------------------------------*/static void make_windowbuttons(CC_REGISTER_ARG struct ctk_window *window){#if CTK_CONF_WINDOWMOVE CTK_BUTTON_NEW(&window->titlebutton, 0, -1, window->titlelen, window->title);#else CTK_LABEL_NEW(&window->titlebutton, 0, -1, window->titlelen, 1, window->title);#endif /* CTK_CONF_WINDOWMOVE */ CTK_WIDGET_ADD(window, &window->titlebutton);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -