void win_show_subwin(ProfWin *window) { int cols = getmaxx(stdscr); int subwin_cols = 0; switch (window->type) { case WIN_CONSOLE: subwin_cols = win_roster_cols(); window->wins.cons.subwin = newpad(PAD_SIZE, subwin_cols); wbkgd(window->wins.cons.subwin, theme_attrs(THEME_TEXT)); wresize(window->win, PAD_SIZE, cols - subwin_cols); win_redraw(window); break; case WIN_MUC: subwin_cols = win_occpuants_cols(); window->wins.muc.subwin = newpad(PAD_SIZE, subwin_cols); wbkgd(window->wins.muc.subwin, theme_attrs(THEME_TEXT)); wresize(window->win, PAD_SIZE, cols - subwin_cols); win_redraw(window); break; default: break; } }
/* The selected window is moved one line up */ static void sel_win_up(scroll_list *sl){ if (sl->sel_win >= 1){ unselect_win( & (sl->wl[sl->sel_win]) ); sl->wl[sl->sel_win].start_row = sl->wl[sl->sel_win - 1].start_row + WL_HIGH_HEIGHT; sl->sel_win--; select_win( & (sl->wl[sl->sel_win]) ); win_redraw(& (sl->wl[sl->sel_win]) ); win_redraw(& (sl->wl[sl->sel_win + 1]) ); }; };
/* The selected window is moved one line down */ static void sel_win_down(scroll_list *sl){ if (sl->sel_win < (sl->num_windows - 1) ){ unselect_win( & (sl->wl[sl->sel_win]) ); sl->sel_win++; select_win( & (sl->wl[sl->sel_win]) ); sl->wl[sl->sel_win].start_row = sl->wl[sl->sel_win -1].start_row + WL_NORMAL_HEIGHT; win_redraw(& (sl->wl[sl->sel_win]) ); win_redraw(& (sl->wl[sl->sel_win - 1]) ); }; };
void win_resize(ProfWin *window) { int cols = getmaxx(stdscr); if (window->layout->type == LAYOUT_SPLIT) { ProfLayoutSplit *layout = (ProfLayoutSplit*)window->layout; if (layout->subwin) { int subwin_cols = 0; if (window->type == WIN_CONSOLE) { subwin_cols = win_roster_cols(); } else if (window->type == WIN_MUC) { subwin_cols = win_occpuants_cols(); } wresize(layout->base.win, PAD_SIZE, cols - subwin_cols); wresize(layout->subwin, PAD_SIZE, subwin_cols); if (window->type == WIN_CONSOLE) { rosterwin_roster(); } else if (window->type == WIN_MUC) { ProfMucWin *mucwin = (ProfMucWin *)window; assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); occupantswin_occupants(mucwin->roomjid); } } else { wresize(layout->base.win, PAD_SIZE, cols); } } else { wresize(window->layout->win, PAD_SIZE, cols); } win_redraw(window); }
void win_hide_subwin(ProfWin *window) { switch (window->type) { case WIN_CONSOLE: if (window->wins.cons.subwin) { delwin(window->wins.cons.subwin); } window->wins.cons.subwin = NULL; window->wins.cons.sub_y_pos = 0; break; case WIN_MUC: if (window->wins.muc.subwin) { delwin(window->wins.muc.subwin); } window->wins.muc.subwin = NULL; window->wins.muc.sub_y_pos = 0; break; default: break; } int cols = getmaxx(stdscr); wresize(window->win, PAD_SIZE, cols); win_redraw(window); }
void popup(char *text, int time_out, int (*keypress_handler) (struct Screen *, int)){ if ( ! popup_active ){ popup_active = 1; screen_visible(cur_screen, 0); popup_save(); popup_win.flags |= WINFLG_VISIBLE; if (keypress_handler != NULL) popup_keypress_handler = keypress_handler; set_keypress_handler(popup_keypress_dispatch); if (time_out > 0){ timer_add(&popup_tmr, time_out, 0); close_popup_task = task_add(&close_popup); } } else { // already a popup active if (time_out > 0){ if (timed_popup) timer_set(&popup_tmr, time_out, 0); else { timer_add(&popup_tmr, time_out, 0); close_popup_task = task_add(close_popup); }; } else { if (timed_popup) { task_del(close_popup_task); timer_del(&popup_tmr); }; }; }; timed_popup = (time_out > 0); win_new_text(&popup_win, text); win_redraw(&popup_win); };
/** * \brief Update colors * * Updates the colors for the progress bar and issues redrawing of the widgets. * * \param widget Context for widget application */ static void app_widget_update_colors(struct widget_context *widget) { gfx_color_t temp; gfx_color_t fg; gfx_color_t bg; switch (widget->color_scheme) { case 1: /* Set colors for color scheme 1 */ fg = COLOR_SCHEME_1_FG; bg = COLOR_SCHEME_1_BG; break; default: /* Set default color scheme */ fg = COLOR_SCHEME_0_FG; bg = COLOR_SCHEME_0_BG; break; } if (widget->color_invert) { temp = bg; bg = fg; fg = temp; } wtk_progress_bar_set_colors(widget->pb, fg, bg); win_redraw(wtk_progress_bar_as_child(widget->pb)); }
void view_repeat_changed(int rpt){ if (rpt == 1) rpt_win.flags &= ~WINFLG_HIDE; else rpt_win.flags |= WINFLG_HIDE; win_redraw(&rpt_win); };
void view_random_changed(int rnd){ if (rnd == 1) rnd_win.flags &= ~WINFLG_HIDE; else rnd_win.flags |= WINFLG_HIDE; win_redraw(&rnd_win); };
void view_single_changed(int sgl){ if (sgl == 1) single_win.flags &= ~WINFLG_HIDE; else single_win.flags |= WINFLG_HIDE; win_redraw(&single_win); };
/* Redraw all the windows of the screen */ void screen_redraw(enum SCREEN screen){ Screen *scr = &(screen_list[screen]); int i; for (i=0; i < scr->wl_size; i++) win_redraw( &( (scr->win_list)[i] ) ); };
void win_mark_received(ProfWin *window, const char *const id) { gboolean received = buffer_mark_received(window->layout->buffer, id); if (received) { win_redraw(window); } }
void win_update_entry_theme(ProfWin *window, const char *const id, theme_item_t theme_item) { ProfBuffEntry *entry = buffer_yield_entry_by_id(window->layout->buffer, id); if (entry) { entry->theme_item = theme_item; win_redraw(window); } }
void win_hide_subwin(ProfWin *window) { if (window->layout->type == LAYOUT_SPLIT) { ProfLayoutSplit *layout = (ProfLayoutSplit*)window->layout; if (layout->subwin) { delwin(layout->subwin); } layout->subwin = NULL; layout->sub_y_pos = 0; int cols = getmaxx(stdscr); wresize(layout->base.win, PAD_SIZE, cols); win_redraw(window); } else { int cols = getmaxx(stdscr); wresize(window->layout->win, PAD_SIZE, cols); win_redraw(window); } }
void win_update_entry_message(ProfWin *window, const char *const id, const char *const message) { ProfBuffEntry *entry = buffer_yield_entry_by_id(window->layout->buffer, id); if (entry) { free(entry->message); entry->message = strdup(message); win_redraw(window); } }
/** * This function sets this radio button to be the single radio button * selected within its group. If another radio button was selected, it * will be deselected. Both widgets will be redrawn if visible. * * \param radio_button Radio button widget to select. */ void wtk_radio_button_select(struct wtk_radio_button *radio_button) { struct wtk_radio_button *old_selected; Assert(radio_button); /* Nothing to do if already selected. */ if (radio_button->group->selected == radio_button) { return; } /* Change selection and redraw both. */ old_selected = radio_button->group->selected; radio_button->group->selected = radio_button; if (old_selected) { win_redraw(old_selected->container); } win_redraw(radio_button->container); }
static void view_version_changed(){ if ( (version_win.flags & WINFLG_VISIBLE)){ version_win.bg_color = WHITE; win_clear(&version_win, 1); version_win.flags &= ~WINFLG_VISIBLE; version_win.bg_color = BLACK; } else { version_win.flags |= WINFLG_VISIBLE; win_redraw(&version_win); }; };
/** * \brief Frame command events handler * * This function handles the command events generated by the widgets. * * \sa wtk_basic_frame_command_handler_t */ static bool widget_frame_command_handler(struct wtk_basic_frame *frame, win_command_t command_data) { char command = (uintptr_t)command_data; switch (command) { case SLIDER_ID: wtk_progress_bar_set_value(progress_bar, wtk_slider_get_value(slider)); break; case BUTTON_ID: /** \todo Add code here to handle button press. */ counter++; win_redraw(wtk_basic_frame_as_child(sub_frame)); break; } return false; }
/** * \brief Frame handler for the application * * Handles all command events from the widgets in the application frame. * * \sa wtk_basic_frame_command_handler_t * * \param frame Pointer to the application frame * \param command_data Command event ID * * \return True if exiting, to destroy the window */ static bool widget_frame_command_handler(struct wtk_basic_frame *frame, win_command_t command_data) { struct widget_context *widget; char command; widget = (struct widget_context *)wtk_basic_frame_get_custom_data(frame); command = (uintptr_t)command_data; switch (command) { case BUTTON_ID: /* Update the plot with the new value as set by the slider */ wtk_plot_add_value(widget->plot, wtk_slider_get_value(widget->slider)); /* Redraw the plot with the new value */ win_redraw(wtk_plot_as_child(widget->plot)); break; } return false; }
/** * \brief Set new slider value. * * Updates the current value and issues a redrawing of the slider if its value * was indeed changed. In this case, the new position of the slider knob is * also computed. * * \param slider Pointer to wtk_slider struct to set new value for. * \param value New value for the slider. * * \return True if slider value was changed. */ bool wtk_slider_set_value(struct wtk_slider *slider, uint8_t value) { struct win_area const *area; uint8_t length; uint8_t option; assert(slider); assert(value <= slider->maximum); option = slider->option; if (option & WTK_SLIDER_INVERT) { value = slider->maximum - value; } if (slider->value != value) { slider->value = value; area = win_get_area(slider->container); /* Get length of slider from window. * wtk_slider_create() asserts that this is an 8-bit value. */ if (option & WTK_SLIDER_VERTICAL) { length = area->size.y; } else { length = area->size.x; } length -= WTK_SLIDER_KNOB_WIDTH; slider->position = wtk_rescale_value(value, slider->maximum, length); win_redraw(slider->container); return true; } else { return false; } }
void win_show_subwin(ProfWin *window) { int cols = getmaxx(stdscr); int subwin_cols = 0; if (window->layout->type != LAYOUT_SPLIT) { return; } if (window->type == WIN_MUC) { subwin_cols = win_occpuants_cols(); } else if (window->type == WIN_CONSOLE) { subwin_cols = win_roster_cols(); } ProfLayoutSplit *layout = (ProfLayoutSplit*)window->layout; layout->subwin = newpad(PAD_SIZE, subwin_cols); wbkgd(layout->subwin, theme_attrs(THEME_TEXT)); wresize(layout->base.win, PAD_SIZE, cols - subwin_cols); win_redraw(window); }
/** Set new caption for label, return false if out of mem. */ bool wtk_label_change(struct wtk_label *label, const char *caption) { Assert(label); Assert(caption); uint8_t new_len = strlen(caption); uint8_t old_len = 0; if (caption) { old_len = strlen(label->caption); } /* Only free old memory if new length is longer than the * previous label. */ if (new_len > old_len) { /* Free old caption, if present. */ if (caption) { membag_free(label->caption); } /* Allocate memory for caption string, and copy text. */ label->caption = membag_alloc((new_len + 1) * sizeof(char)); if (!label->caption) { goto outofmem_caption; } } wtk_copy_string(label->caption, caption); /* Redraw if visible. */ win_redraw(label->container); return true; outofmem_caption: return false; }
/** * \brief Set new progress bar value. * * Updates the current value and issues a redrawing of the progress bar if its * value was indeed changed. In this case, a new end position for the progress * bar's fill area is also computed. * * \param bar Pointer to wtk_progress_bar struct to set new value for. * \param value New value for the progress bar. * * \return True if progress bar's value was changed. */ bool wtk_progress_bar_set_value(struct wtk_progress_bar *bar, uint8_t value) { uint8_t length; uint8_t option; uint8_t maximum; struct win_area const *area; Assert(bar); Assert(value <= bar->maximum); if (value != bar->value) { bar->value = value; option = bar->option; maximum = bar->maximum; area = win_get_area(bar->container); /* Get length of progress bar from window. */ if (option & WTK_PROGRESS_BAR_VERTICAL) { length = area->size.y; } else { length = area->size.x; } length -= 2; if (option & WTK_PROGRESS_BAR_INVERT) { value = maximum - value; } bar->position = wtk_rescale_value(value, maximum, length); win_redraw(bar->container); return true; } else { return false; } }
/** * \brief Slider event handler. * * This is the window event handler for slider widgets. It handles the three * relevant event types sent to a slider's container window, i.e., drawing, * pointer and destroy events.\par * * For POINTER events, the slider value is only updated when the pointer moves, * and not upon press or release events. The handler will grab the pointer and * allow for it to move outside the actual widget window and still control the * slider knob. * * \param win Window receiving the event. * \param type The event type. * \param data Custom data, depending on event type. * * \return True if the event was recognized and accepted. */ static bool wtk_slider_handler(struct win_window *win, enum win_event_type type, void const *data) { struct win_pointer_event const *event; struct win_clip_region const *clip; struct win_command_event command; struct win_area const *area; struct wtk_slider *slider; struct win_point origin; gfx_color_t knob_color; gfx_coord_t position; gfx_coord_t length; uint8_t option; uint8_t value; bool send_command; slider = (struct wtk_slider *)win_get_custom_data(win); // There should not be other windows in this widget. assert(win == slider->container); switch (type) { case WIN_EVENT_DRAW: /* For DRAW events, the data parameter points to the * clipping region. */ clip = (struct win_clip_region const *)data; area = win_get_area(win); option = slider->option; if (slider->state == WTK_SLIDER_NORMAL) { knob_color = WTK_SLIDER_KNOB_COLOR_NORMAL; } else { knob_color = WTK_SLIDER_KNOB_COLOR_MOVING; } // Draw slider frame border. gfx_draw_rect(clip->origin.x, clip->origin.y, area->size.x, area->size.y, WTK_SLIDER_BORDER_COLOR); // Draw slider frame background within frame. gfx_draw_filled_rect(clip->origin.x + 1, clip->origin.y + 1, area->size.x - 2, area->size.y - 2, WTK_SLIDER_BACKGROUND_COLOR); // Draw the slider knob according to configured orientation. if (option & WTK_SLIDER_VERTICAL) { // Draw slider knob border. gfx_draw_rect(clip->origin.x, clip->origin.y + slider->position, area->size.x, WTK_SLIDER_KNOB_WIDTH, WTK_SLIDER_BORDER_COLOR); // Draw slider knob. gfx_draw_filled_rect(clip->origin.x + 1, clip->origin.y + slider->position + 1, area->size.x - 2, WTK_SLIDER_KNOB_WIDTH - 2, knob_color); } else { gfx_draw_rect(clip->origin.x + slider->position, clip->origin.y, WTK_SLIDER_KNOB_WIDTH, area->size.y, WTK_SLIDER_BORDER_COLOR); gfx_draw_filled_rect(clip->origin.x + slider->position + 1, clip->origin.y + 1, WTK_SLIDER_KNOB_WIDTH - 2, area->size.y - 2, knob_color); } /* Always accept DRAW events, as the return value is ignored * anyway for that event type. */ return true; case WIN_EVENT_POINTER: /* For POINTER events, the data parameter points to the pointer * event information. */ event = (struct win_pointer_event const *)data; area = win_get_area(win); option = slider->option; send_command = false; origin = slider->root_pos; switch (event->type) { case WIN_POINTER_PRESS: /* Grab the pointer and redraw a highlighted slider. * Slider value is not updated yet. */ if (slider->state == WTK_SLIDER_NORMAL) { slider->state = WTK_SLIDER_MOVING; win_grab_pointer(win); win_redraw(win); }; #if WTK_SLIDER_PARENT_MOVE_SUPPORT // Update root position. win_translate_win_to_root(win, &slider->root_pos); #endif break; case WIN_POINTER_MOVE: /* The slider is only updated when the pointer moves * and the window was previously pressed. The pointer * does not need to remain within the window to control * the knob as only the position along the slider's * direction of orientation is used. */ if (slider->state == WTK_SLIDER_MOVING) { /* Get the position of the pointer relative to * slider knob's origin, and the length of the * slider itself. */ if (option & WTK_SLIDER_VERTICAL) { position = event->pos.y - origin.y; length = area->size.y; } else { position = event->pos.x - origin.x; length = area->size.x; } // Subtract offsets due to slider knob size. position -= WTK_SLIDER_KNOB_WIDTH / 2; length -= WTK_SLIDER_KNOB_WIDTH; /* Bound the value if pointer is outside window. * Otherwise, compute the slider value from the * knob position. */ if (position < 0) { value = 0; } else if (position > length) { value = slider->maximum; } else { value = wtk_rescale_value(position, length, slider->maximum); } // Update slider only if this is a new value. if (slider->value != value) { slider->value = value; /* Compute knob position from value to * get correct positioning. */ slider->position = wtk_rescale_value(value, slider->maximum, length); if (option & WTK_SLIDER_CMD_MOVE) { send_command = true; } win_redraw(win); } } break; case WIN_POINTER_RELEASE: /* Release the pointer and redraw a normal slider. * The slider's value is not updated. Hence, a pointer * press directly followed by a release will leave the * slider value unchanged. */ if (slider->state == WTK_SLIDER_MOVING) { slider->state = WTK_SLIDER_NORMAL; win_grab_pointer(NULL); win_redraw(win); if (option & WTK_SLIDER_CMD_RELEASE) { send_command = true; } } break; default: break; } // Prepare and send command, if it was flagged. if (send_command) { command.sender = slider->container; command.recipient = slider->container; command.data = slider->command; win_queue_command_event(&command); } /* Accept all POINTER events since all acitivity inside the * widget window is relevant. */ return true; case WIN_EVENT_DESTROY: /* Memory allocated for windows will be automatically destroyed * by the window system. We must destroy other allocations. */ membag_free(slider); /* Always accept DESTROY events, as the return value is ignored * anyway for that event type. */ return true; default: // Reject unknown event types. return false; } }
/** * This function sets the value of the check box according to the "selected" * parameter. * The graphics will be updated if the box is visible. * * \param check_box Check box to update. * \param selected Value to set for checkbox. True if check box is selected, * false otherwise */ void wtk_check_box_set(struct wtk_check_box *check_box, bool selected) { Assert(check_box); check_box->selected = selected; win_redraw(check_box->container); }
/** * This function is the window event handler for radio button widgets. * It handles all events sent to the windows composing the widget. * * \param win Window receiving the event. * \param type The event type. * \param data Custom data, depending on event type. * * \return True if the event was recognized and accepted. */ static bool wtk_radio_button_handler(struct win_window *win, enum win_event_type type, void const *data) { struct win_command_event command; /* Custom data for windows of a widget points back to the widget itself. */ struct wtk_radio_button *radio_button = (struct wtk_radio_button *)win_get_custom_data(win); switch (type) { case WIN_EVENT_DRAW: { /* For DRAW events, the data parameter points to the * clipping region. */ struct win_clip_region const *clip = (struct win_clip_region const *)data; /* There should not be other windows in this widget. */ Assert(win == radio_button->container); /* Draw radio button circle. */ gfx_draw_circle(clip->origin.x + WTK_RADIOBUTTON_BUTTON_X, clip->origin.y + WTK_RADIOBUTTON_BUTTON_Y, WTK_RADIOBUTTON_RADIUS, WTK_RADIOBUTTON_BUTTON_COLOR, GFX_WHOLE); /* Draw radio button filled circle background. */ if (WTK_RADIOBUTTON_BACKGROUND_COLOR != GFX_COLOR_TRANSPARENT) { gfx_draw_filled_circle(clip->origin.x + WTK_RADIOBUTTON_BUTTON_X, clip->origin.y + WTK_RADIOBUTTON_BUTTON_Y, WTK_RADIOBUTTON_RADIUS - 1, WTK_RADIOBUTTON_BACKGROUND_COLOR, GFX_WHOLE); } /* Draw radio button select marker if selected. */ if (radio_button->group->selected == radio_button) { gfx_draw_filled_circle(clip->origin.x + WTK_RADIOBUTTON_BUTTON_X, clip->origin.y + WTK_RADIOBUTTON_BUTTON_Y, WTK_RADIOBUTTON_RADIUS - 2, WTK_RADIOBUTTON_SELECT_COLOR, GFX_WHOLE); } /* Draw caption. */ gfx_draw_string(radio_button->caption, clip->origin.x + WTK_RADIOBUTTON_CAPTION_X, clip->origin.y + WTK_RADIOBUTTON_CAPTION_Y, &sysfont, GFX_COLOR_TRANSPARENT, WTK_RADIOBUTTON_CAPTION_COLOR); /* Always accept DRAW events, as the return value is * ignored anyway for that event type. */ return true; } case WIN_EVENT_POINTER: { /* There should not be other windows in this widget. */ Assert(win == radio_button->container); /* For POINTER events, the data parameter points to the * pointer event information. */ struct win_pointer_event const *event = (struct win_pointer_event const *)data; switch (event->type) { case WIN_POINTER_PRESS: /* When radio button pressed, grab pointer and * wait for release inside widget borders. * Other widgets won't get pointer events * before it is released, and the pointer * ungrabbed by us. */ if (radio_button->state == WTK_RADIOBUTTON_NORMAL) { win_grab_pointer(radio_button-> container); radio_button->state = WTK_RADIOBUTTON_PRESSED; win_redraw(radio_button->container); } break; case WIN_POINTER_RELEASE: /* When button released, take action only if * released inside widget extents. */ if (radio_button->state == WTK_RADIOBUTTON_PRESSED) { bool is_inside; /* Ungrab pointer. */ win_grab_pointer(NULL); radio_button->state = WTK_RADIOBUTTON_NORMAL; win_redraw(radio_button->container); /* Check release position. */ is_inside = win_is_inside_window (radio_button-> container, &(event->pos)); /* Select this radio button if inside. */ if (is_inside) { wtk_radio_button_select (radio_button); /* Send non-zero command. */ if (radio_button->command) { command.sender = radio_button-> container; command.recipient = radio_button-> container; command.data = radio_button->command; win_queue_command_event (&command); } } } break; default: break; } /* Accept all POINTER events since all acitivity inside * the widget extents is relevant to us. */ return true; } case WIN_EVENT_DESTROY: /* There should not be other windows in this widget. */ Assert(win == radio_button->container); /* Memory allocated for windows will be automatically destroyed * by the window system. We must destroy other allocations. */ membag_free(radio_button->caption); /* Destroy radio group as well if we are the last one in the * group. If not, remove ourselves from the group. */ --(radio_button->group->num_references); if (!radio_button->group->num_references) { membag_free(radio_button->group); } else { if (radio_button->group->selected == radio_button) { radio_button->group->selected = NULL; } } membag_free(radio_button); /* Always accept DESTROY events, as the return value is ignored * anyway for that event type. */ return true; default: /* Reject unknown event types. */ return false; } }
/** * This function toggles the value of a check box. If it is not selected, it * will be set to a selected/checked state, and vice versa. The graphics will * be updated if the box is visible. * * \param check_box Check box to toggle. */ void wtk_check_box_toggle(struct wtk_check_box *check_box) { Assert(check_box); check_box->selected = !check_box->selected; win_redraw(check_box->container); }
/** * This function is the window event handler for icon button widgets. * It handles all events sent to the windows composing the widget. * * \param win Window receiving the event. * \param type The event type. * \param data Custom data, depending on event type. * * \return True if the event was recognized and accepted. */ static bool wtk_icon_button_handler(struct win_window *win, enum win_event_type type, void const *data) { struct win_command_event command; /* Custom data for windows of a widget points back to the widget itself. */ struct wtk_icon_button *icon_button = (struct wtk_icon_button *)win_get_custom_data(win); switch (type) { case WIN_EVENT_DRAW: { /* For DRAW events, the data parameter points to the * clipping region. */ struct win_clip_region const *clip = (struct win_clip_region const *)data; struct win_area const *area = win_get_area(win); /* There should not be other windows in this widget. */ Assert(win == icon_button->container); /* Draw icon button select marker if selected. */ if (icon_button->group->selected == icon_button) { gfx_draw_rect(clip->origin.x, clip->origin.y, area->size.x, area->size.y, WTK_ICONBUTTON_SELECT_COLOR); } /* Always accept DRAW events, as the return value is * ignored anyway for that event type. */ return true; } case WIN_EVENT_POINTER: { /* There should not be other windows in this widget. */ Assert(win == icon_button->container); /* For POINTER events, the data parameter points to the * pointer event information. */ struct win_pointer_event const *event = (struct win_pointer_event const *)data; switch (event->type) { case WIN_POINTER_PRESS: /* When icon button pressed, grab pointer and * wait for release inside widget borders. * Other widgets won't get pointer events * before it is released, and the pointer * ungrabbed by us. */ if (icon_button->state == WTK_ICONBUTTON_NORMAL) { win_grab_pointer(icon_button->container); icon_button->state = WTK_ICONBUTTON_PRESSED; win_redraw(icon_button->container); } break; case WIN_POINTER_RELEASE: /* When button released, take action only if * released inside widget extents. */ if (icon_button->state == WTK_ICONBUTTON_PRESSED) { bool is_inside; /* Ungrab pointer. */ win_grab_pointer(NULL); icon_button->state = WTK_ICONBUTTON_NORMAL; win_redraw(icon_button->container); /* Check release position. */ is_inside = win_is_inside_window (icon_button-> container, &(event->pos)); /* Select this icon button if inside. */ if (is_inside) { wtk_icon_button_select (icon_button); /* Send non-zero command. */ if (icon_button->command) { command.sender = icon_button-> container; command.recipient = icon_button-> container; command.data = icon_button->command; win_queue_command_event (&command); } } } break; default: break; } /* Accept all POINTER events since all activity inside * the widget extents is relevant to us. */ return true; } case WIN_EVENT_DESTROY: /* There should not be other windows in this widget. */ Assert(win == icon_button->container); /* Destroy icon group as well if we are the last one in the * group. If not, remove ourselves from the group. */ --(icon_button->group->num_references); if (!icon_button->group->num_references) { membag_free(icon_button->group); } else { if (icon_button->group->selected == icon_button) { icon_button->group->selected = NULL; } } membag_free(icon_button); /* Always accept DESTROY events, as the return value is ignored * anyway for that event type. */ return true; default: /* Reject unknown event types. */ return false; } }
/** * This function is the window event handler for check box widgets. * It handles all events sent to the windows composing the widget. * * \param win Window receiving the event. * \param type The event type. * \param data Custom data, depending on event type. * * \return True if the event was recognized and accepted. */ static bool wtk_check_box_handler(struct win_window *win, enum win_event_type type, void const *data) { struct win_command_event command; /* Custom data for windows of a widget points back to the widget itself. */ struct wtk_check_box *check_box = (struct wtk_check_box *)win_get_custom_data(win); switch (type) { case WIN_EVENT_DRAW: { /* There should not be other windows in this widget. */ Assert(win == check_box->container); /* For DRAW events, the data parameter points to the * clipping region. */ struct win_clip_region const *clip = (struct win_clip_region const *)data; /* Draw check box square. */ gfx_draw_rect(clip->origin.x + WTK_CHECKBOX_BOX_X, clip->origin.y + WTK_CHECKBOX_BOX_Y, WTK_CHECKBOX_BOX_SIZE, WTK_CHECKBOX_BOX_SIZE, WTK_CHECKBOX_BOX_COLOR); /* Draw check box square background. */ if (WTK_CHECKBOX_BACKGROUND_COLOR != GFX_COLOR_TRANSPARENT) { gfx_draw_filled_rect(clip->origin.x + WTK_CHECKBOX_BOX_X + 1, clip->origin.y + WTK_CHECKBOX_BOX_Y + 1, WTK_CHECKBOX_BOX_SIZE - 2, WTK_CHECKBOX_BOX_SIZE - 2, WTK_CHECKBOX_BACKGROUND_COLOR); } /* Draw check box select marker if selected. */ if (check_box->selected) { gfx_draw_filled_rect(clip->origin.x + WTK_CHECKBOX_BOX_X + 2, clip->origin.y + WTK_CHECKBOX_BOX_Y + 2, WTK_CHECKBOX_BOX_SIZE - 4, WTK_CHECKBOX_BOX_SIZE - 4, WTK_CHECKBOX_SELECT_COLOR); } /* Draw caption. */ gfx_draw_string(check_box->caption, clip->origin.x + WTK_CHECKBOX_CAPTION_X, clip->origin.y + WTK_CHECKBOX_CAPTION_Y, &sysfont, GFX_COLOR_TRANSPARENT, WTK_CHECKBOX_CAPTION_COLOR); /* Always accept DRAW events, as the return value is * ignored anyway for that event type. */ return true; } case WIN_EVENT_POINTER: { /* There should not be other windows in this widget. */ Assert(win == check_box->container); /* For POINTER events, the data parameter points to the * pointer event information. */ struct win_pointer_event const *event = (struct win_pointer_event const *)data; switch (event->type) { case WIN_POINTER_PRESS: /* When check box pressed, grab pointer and * wait for release inside widget borders. * Other widgets won't get pointer events * before it is released, and the pointer * ungrabbed by us. */ if (check_box->state == WTK_CHECKBOX_NORMAL) { win_grab_pointer(check_box->container); check_box->state = WTK_CHECKBOX_PRESSED; win_redraw(check_box->container); } break; case WIN_POINTER_RELEASE: /* When check box released, take action only if * released inside widget extents. */ if (check_box->state == WTK_CHECKBOX_PRESSED) { bool is_inside; /* Ungrab pointer. */ win_grab_pointer(NULL); check_box->state = WTK_CHECKBOX_NORMAL; win_redraw(check_box->container); /* Check release position. */ is_inside = win_is_inside_window (check_box->container, &(event->pos)); /* Toggle check box if inside. */ if (is_inside) { wtk_check_box_toggle(check_box); /* Send non-zero command. */ if (check_box->command) { command.sender = check_box->container; command.recipient = check_box->container; command.data = check_box->command; win_queue_command_event (&command); } } } break; default: break; } /* Accept all POINTER events since all acitivity inside * the widget extents is relevant to us. */ return true; } case WIN_EVENT_DESTROY: /* There should not be other windows in this widget. */ Assert(win == check_box->container); /* Memory allocated for windows will be automatically destroyed * by the window system. We must destroy other allocations. */ membag_free(check_box->caption); membag_free(check_box); /* Always accept DESTROY events, as the return value is ignored * anyway for that event type. */ return true; default: /* Reject unknown event types. */ return false; } }
/** * This function is the window event handler for button widgets. * It handles all events sent to the windows composing the widget. * * \param win Window receiving the event. * \param type The event type. * \param data Custom data, depending on event type. * * \return True if the event was recognized and accepted. */ static bool wtk_button_handler(struct win_window *win, enum win_event_type type, void const *data) { /* Custom data for windows of a widget points back to the widget itself. */ struct wtk_button *button = (struct wtk_button *)win_get_custom_data(win); switch (type) { case WIN_EVENT_DRAW: { /* For DRAW events, the data parameter points to the * clipping region. */ struct win_clip_region const *clip = (struct win_clip_region const *)data; struct win_area const *area = win_get_area(win); /* Preare background and caption colors depending on state of * button. If pressed/highlighted, the colors are inverted. */ gfx_color_t background_color; gfx_color_t caption_color; /* There should not be other windows in this widget. */ Assert(win == button->container); switch (button->state) { case WTK_BUTTON_NORMAL: background_color = WTK_BUTTON_BACKGROUND_COLOR; caption_color = WTK_BUTTON_CAPTION_COLOR; break; case WTK_BUTTON_PRESSED: background_color = WTK_BUTTON_CAPTION_COLOR; caption_color = WTK_BUTTON_BACKGROUND_COLOR; break; default: Assert(false); background_color = WTK_BUTTON_BACKGROUND_COLOR; caption_color = WTK_BUTTON_CAPTION_COLOR; } /* Draw background. */ gfx_draw_filled_rect(clip->origin.x, clip->origin.y, area->size.x, area->size.y, background_color); /* Draw border. */ gfx_draw_rect(clip->origin.x, clip->origin.y, area->size.x, area->size.y, WTK_BUTTON_BORDER_COLOR); /* Draw caption. */ gfx_draw_string_aligned(button->caption, clip->origin.x + (area->size.x / 2), clip->origin.y + (area->size.y / 2), &sysfont, GFX_COLOR_TRANSPARENT, caption_color, TEXT_POS_CENTER, TEXT_ALIGN_CENTER); /* Always accept DRAW events, as the return value is * ignored anyway for that event type. */ return true; } case WIN_EVENT_POINTER: { /* There should not be other windows in this widget. */ Assert(win == button->container); /* For POINTER events, the data parameter points to the * pointer event information. */ struct win_pointer_event const *event = (struct win_pointer_event const *)data; switch (event->type) { case WIN_POINTER_PRESS: /* When button pressed, grab pointer and wait * for release inside button borders. Other * widgets won't get pointer events before it * is released, and the pointer ungrabbed by * us. */ if (button->state == WTK_BUTTON_NORMAL) { win_grab_pointer(button->container); button->state = WTK_BUTTON_PRESSED; win_redraw(button->container); } break; case WIN_POINTER_RELEASE: /* When button released, take action only if * released inside widget extents. */ if (button->state == WTK_BUTTON_PRESSED) { /* Ungrab pointer. */ win_grab_pointer(NULL); button->state = WTK_BUTTON_NORMAL; win_redraw(button->container); /* Check release position. */ bool isInside = win_is_inside_window (button->container, &(event->pos)); /* Send command event if inside. */ if (isInside) { struct win_command_event command; command.sender = button-> container; command.recipient = button-> container; command.data = button-> command; win_queue_command_event (&command); } } break; default: break; } /* Accept all POINTER events since all acitivity inside * the widget extents is relevant to us. */ return true; } case WIN_EVENT_DESTROY: { /* There should not be other windows in this widget. */ Assert(win == button->container); /* Memory allocated for windows will be automatically * destroyed by the window system. We must destroy * other allocations. */ membag_free(button->caption); membag_free(button); /* Always accept DESTROY events, as the return value is * ignored anyway for that event type. */ return true; } default: /* Reject unknown event types. */ return false; } }