// // Scrollpane - Initializes a Scrollpane. // void EZ_scrollpane_Init(ez_scrollpane_t *scrollpane, ez_tree_t *tree, ez_control_t *parent, char *name, char *description, int x, int y, int width, int height, ez_control_flags_t flags) { int rh_size_h = 0; int rh_size_v = 0; ez_control_t *scrollpane_ctrl = (ez_control_t *)scrollpane; // Initialize the inherited class first. EZ_control_Init(&scrollpane->super, tree, parent, name, description, x, y, width, height, flags); // Initilize the button specific stuff. ((ez_control_t *)scrollpane)->CLASS_ID = EZ_SCROLLPANE_ID; ((ez_control_t *)scrollpane)->ext_flags |= (flags | control_focusable | control_contained | control_resizeable); // Override control events. CONTROL_REGISTER_EVENT(scrollpane, EZ_scrollpane_OnResize, OnResize, ez_control_t); // Scrollpane specific events. CONTROL_REGISTER_EVENT(scrollpane, EZ_scrollpane_OnTargetChanged, OnTargetChanged, ez_scrollpane_t); CONTROL_REGISTER_EVENT(scrollpane, EZ_scrollpane_OnScrollbarThicknessChanged, OnScrollbarThicknessChanged, ez_scrollpane_t); scrollpane->scrollbar_thickness = 10; rh_size_h = (scrollpane_ctrl->ext_flags & control_resize_h) ? scrollpane_ctrl->resize_handle_thickness : 0; rh_size_v = (scrollpane_ctrl->ext_flags & control_resize_v) ? scrollpane_ctrl->resize_handle_thickness : 0; EZ_control_SetMinVirtualSize(scrollpane_ctrl, 1, 1); scrollpane->int_flags |= (show_h_scrollbar | show_v_scrollbar); // Create vertical scrollbar. { scrollpane->v_scrollbar = EZ_scrollbar_Create(tree, scrollpane_ctrl, "Vertical scrollbar", "", 0, 0, 10, 10, control_anchor_viewport); EZ_control_SetVisible((ez_control_t *)scrollpane->v_scrollbar, true); EZ_control_SetPosition((ez_control_t *)scrollpane->v_scrollbar, -rh_size_h, rh_size_v); EZ_control_SetAnchor((ez_control_t *)scrollpane->v_scrollbar, (anchor_top | anchor_bottom | anchor_right)); EZ_scrollbar_SetTargetIsParent(scrollpane->v_scrollbar, false); EZ_control_AddChild(scrollpane_ctrl, (ez_control_t *)scrollpane->v_scrollbar); } // Create horizontal scrollbar. { scrollpane->h_scrollbar = EZ_scrollbar_Create(tree, (ez_control_t *)scrollpane, "Horizontal scrollbar", "", 0, 0, 10, 10, control_anchor_viewport); EZ_control_SetVisible((ez_control_t *)scrollpane->h_scrollbar, true); EZ_control_SetPosition((ez_control_t *)scrollpane->h_scrollbar, rh_size_h, -rh_size_v); EZ_control_SetAnchor((ez_control_t *)scrollpane->h_scrollbar, (anchor_left | anchor_bottom | anchor_right)); EZ_scrollbar_SetTargetIsParent(scrollpane->h_scrollbar, false); EZ_scrollbar_SetIsVertical(scrollpane->h_scrollbar, false); EZ_control_AddChild(scrollpane_ctrl, (ez_control_t *)scrollpane->h_scrollbar); } EZ_scrollpane_ResizeScrollbars(scrollpane); }
// // Scrollbar - Mouse event. // int EZ_scrollbar_OnMouseEvent(ez_control_t *self, mouse_state_t *ms) { ez_scrollbar_t *scrollbar = (ez_scrollbar_t *)self; ez_control_t *back_ctrl = (ez_control_t *)scrollbar->back; ez_control_t *forward_ctrl = (ez_control_t *)scrollbar->forward; ez_control_t *slider_ctrl = (ez_control_t *)scrollbar->slider; int m_delta_x = Q_rint(ms->x - ms->x_old); int m_delta_y = Q_rint(ms->y - ms->y_old); qbool mouse_handled = false; qbool mouse_handled_tmp = false; mouse_handled = EZ_control_OnMouseEvent(self, ms); if (!mouse_handled) { if (scrollbar->int_flags & sliding) { if (scrollbar->orientation == vertical) { // float scroll_ratio = 0; // Reposition the slider within the scrollbar control based on where the mouse moves. int new_y = slider_ctrl->y + m_delta_y; // Only allow moving the scroll slider in the area between the two buttons (the scroll area). clamp(new_y, back_ctrl->height, (self->height - forward_ctrl->height - slider_ctrl->height)); EZ_control_SetPosition(slider_ctrl, 0, new_y); mouse_handled = true; } else { int new_x = slider_ctrl->x + m_delta_x; clamp(new_x, back_ctrl->width, (self->width - forward_ctrl->width - slider_ctrl->width)); EZ_control_SetPosition(slider_ctrl, new_x, 0); mouse_handled = true; } // Make sure we don't try to set the position of the slider // as the parents scroll position changes, like normal. scrollbar->int_flags |= scrolling; if (scrollbar->ext_flags & target_parent) { EZ_scrollbar_CalculateParentScrollPosition(scrollbar, self->parent); } else { EZ_scrollbar_CalculateParentScrollPosition(scrollbar, scrollbar->target); } scrollbar->int_flags &= ~scrolling; } } CONTROL_EVENT_HANDLER_CALL(&mouse_handled_tmp, self, ez_control_t, OnMouseEvent, ms); mouse_handled = (mouse_handled | mouse_handled_tmp); return mouse_handled; }
// // Scrollbar - Updates the slider position of the scrollbar based on the parents scroll position. // static void EZ_scrollbar_UpdateSliderBasedOnTarget(ez_scrollbar_t *scrollbar, ez_control_t *target) { ez_control_t *self = (ez_control_t *)scrollbar; ez_control_t *back_ctrl = (ez_control_t *)scrollbar->back; ez_control_t *forward_ctrl = (ez_control_t *)scrollbar->forward; ez_control_t *slider_ctrl = (ez_control_t *)scrollbar->slider; float scroll_ratio; if (!target) { return; } // Don't do anything if this is the user moving the slider using the mouse. if (scrollbar->int_flags & scrolling) { return; } if (scrollbar->orientation == vertical) { int new_y; // Find how far down on the parent control we're scrolled (percentage). scroll_ratio = fabs(target->virtual_y / (float)target->virtual_height); // Calculate the position of the slider by multiplying the scroll areas // height with the scroll ratio. new_y = back_ctrl->height + Q_rint(scroll_ratio * scrollbar->scroll_area); clamp(new_y, back_ctrl->height, (self->height - forward_ctrl->height - slider_ctrl->height)); EZ_control_SetPosition(slider_ctrl, 0, new_y); } else { int new_x; scroll_ratio = fabs(target->virtual_x / (float)target->virtual_width); new_x = back_ctrl->width + Q_rint(scroll_ratio * scrollbar->scroll_area); clamp(new_x, back_ctrl->width, (self->width - forward_ctrl->width - slider_ctrl->width)); EZ_control_SetPosition(slider_ctrl, new_x, 0); } }
// // Scrollbar - Repositions the back / forward buttons according to orientation. // static void EZ_scrollbar_RepositionScrollButtons(ez_scrollbar_t *scrollbar) { ez_control_t *self = (ez_control_t *)scrollbar; ez_control_t *back_ctrl = (ez_control_t *)scrollbar->back; ez_control_t *slider_ctrl = (ez_control_t *)scrollbar->slider; ez_control_t *forward_ctrl = (ez_control_t *)scrollbar->forward; // Let the super class do it's thing first. EZ_control_OnResize(self, NULL); if (scrollbar->orientation == vertical) { // Up button. EZ_control_SetSize(back_ctrl, self->width, self->width); EZ_control_SetAnchor(back_ctrl, anchor_left | anchor_top | anchor_right); // Slider. EZ_control_SetPosition(slider_ctrl, 0, self->width); EZ_control_SetAnchor(slider_ctrl, anchor_left | anchor_right); // Down button. EZ_control_SetSize(forward_ctrl, self->width, self->width); EZ_control_SetAnchor(forward_ctrl, anchor_left | anchor_bottom | anchor_right); scrollbar->scroll_area = self->height - (forward_ctrl->height + back_ctrl->height); } else { // Left button. EZ_control_SetSize(back_ctrl, self->height, self->height); EZ_control_SetAnchor(back_ctrl, anchor_left | anchor_top | anchor_bottom); // Slider. EZ_control_SetPosition(slider_ctrl, self->height, 0); EZ_control_SetAnchor(slider_ctrl, anchor_top | anchor_bottom); // Right button. EZ_control_SetSize(forward_ctrl, self->height, self->height); EZ_control_SetAnchor(forward_ctrl, anchor_top | anchor_bottom | anchor_right); scrollbar->scroll_area = self->width - (forward_ctrl->width + back_ctrl->width); } }
// // Scrollpane - The target control changed. // int EZ_scrollpane_OnTargetChanged(ez_control_t *self, void *ext_event_info) { ez_scrollpane_t *scrollpane = (ez_scrollpane_t *)self; // Clean up the old target. if (scrollpane->prev_target) { EZ_eventhandler_Remove(scrollpane->prev_target->event_handlers.OnVirtualResize, EZ_scrollpane_OnTargetVirtualResize, false); EZ_control_RemoveChild(self, scrollpane->target); EZ_control_SetMovesParent(scrollpane->prev_target, false); } // Set the new target for the scrollbars so they know what to scroll. EZ_scrollbar_SetTarget(scrollpane->v_scrollbar, scrollpane->target); EZ_scrollbar_SetTarget(scrollpane->h_scrollbar, scrollpane->target); if (scrollpane->target) { // Subscribe to the targets resize and scroll events. EZ_control_AddOnVirtualResize(scrollpane->target, EZ_scrollpane_OnTargetVirtualResize, scrollpane); EZ_control_AddChild(self, scrollpane->target); EZ_control_SetScrollable(scrollpane->target, true); EZ_control_SetMovable(scrollpane->target, true); EZ_control_SetResizeableBoth(scrollpane->target, true); EZ_control_SetResizeable(scrollpane->target, true); // Reposition the target inside the scrollpane. EZ_control_SetPosition(scrollpane->target, 0, 0); EZ_control_SetSize(scrollpane->target, (self->width - scrollpane->scrollbar_thickness), (self->height - scrollpane->scrollbar_thickness)); EZ_control_SetAnchor(scrollpane->target, (anchor_left | anchor_right | anchor_top | anchor_bottom)); // Make sure the target is drawn infront of the scrollpane. EZ_control_SetDrawOrder(scrollpane->target, ((ez_control_t *)scrollpane)->draw_order + 1, true); // When moving the target move the scrollpane with it // and don't allow moving the target inside of the scrollpane. EZ_control_SetMovesParent(scrollpane->target, true); // Resize the scrollbars / target to fit properly. EZ_scrollpane_DetermineScrollbarVisibility(scrollpane); EZ_scrollpane_ResizeScrollbars(scrollpane); EZ_scrollpane_AdjustTargetSize(scrollpane); CONTROL_RAISE_EVENT(NULL, (ez_control_t *)scrollpane->target, ez_control_t, OnResize, NULL); CONTROL_RAISE_EVENT(NULL, (ez_control_t *)scrollpane->target, ez_control_t, OnMove, NULL); } CONTROL_EVENT_HANDLER_CALL(NULL, scrollpane, ez_scrollpane_t, OnTargetChanged, NULL); return 0; }
// // Listview item - Lays out the control. // void EZ_listviewitem_LayoutControl(ez_listviewitem_t *self) { int i; int x = 0; ez_control_t *ctrl = (ez_control_t *)self; ez_control_t *lblctrl = NULL; for (i = 0; i < self->item_count; i++) { if (!self->item_visibile[i]) continue; lblctrl = (ez_control_t *)self->items[i]; // Space out the labels in columns. EZ_control_SetPosition(lblctrl, x, 0); x += lblctrl->width + self->item_gap; // Make sure we reset the height if some naughty person changed it since last time. EZ_control_SetSize(lblctrl, lblctrl->width, ctrl->height); } }
// // Window - Initializes a window. // void EZ_window_Init(ez_window_t *window, ez_tree_t *tree, ez_control_t *parent, char *name, char *description, int x, int y, int width, int height, ez_control_flags_t flags) { ez_control_t *window_ctrl = (ez_control_t *)window; ez_control_t *titlebar_ctrl = NULL; ez_control_t *scrollpane_ctrl = NULL; int rh_size = 0; // Initialize the inherited class first. EZ_control_Init(&window->super, tree, parent, name, description, x, y, width, height, flags); ((ez_control_t *)window)->CLASS_ID = EZ_WINDOW_ID; ((ez_control_t *)window)->ext_flags |= (flags | control_focusable | control_contained | control_resizeable); rh_size = window_ctrl->resize_handle_thickness; // Set the background. EZ_control_SetBackgroundImage(window_ctrl, EZ_WINDOW_DEFAULT_BACKGROUND_IMAGE); EZ_control_SetBackgroundImageOpacity(window_ctrl, 1.0); EZ_control_SetBackgroundImageEdgePercentage(window_ctrl, 20); // Title bar. { // Set the tilebar to move it's parent. window->titlebar = EZ_control_Create(tree, window_ctrl, "Window titlebar", NULL, rh_size, rh_size, window_ctrl->width, 15, (control_focusable | control_move_parent | control_movable | control_resizeable | control_enabled | control_anchor_viewport)); titlebar_ctrl = (ez_control_t *)window->titlebar; EZ_control_SetBackgroundImage(titlebar_ctrl, "gfx/ui/ez_titlebar"); // Set the size to fit within the resize handles. EZ_control_SetSize(titlebar_ctrl, (window_ctrl->width - (2 * rh_size)), 15); EZ_control_SetAnchor(titlebar_ctrl, (anchor_left | anchor_top | anchor_right)); EZ_control_SetDrawOrder(titlebar_ctrl, window_ctrl->draw_order + 1, true); // Close button. { #define CLOSE_BUTTON_EDGE_GAP 2 int cb_sidelength = 0; ez_control_t *close_ctrl = NULL; window->close_button = EZ_button_Create(tree, titlebar_ctrl, "Close button", NULL, 0, 0, 10, 10, control_enabled); close_ctrl = (ez_control_t *)window->close_button; cb_sidelength = (titlebar_ctrl->height - (2 * CLOSE_BUTTON_EDGE_GAP)); // Position the close button CLOSE_BUTTON_EDGE_GAP number of pixels from the edge // of the titlebar, and size it accordingly. EZ_control_SetPosition(close_ctrl, -CLOSE_BUTTON_EDGE_GAP, CLOSE_BUTTON_EDGE_GAP); EZ_control_SetSize(close_ctrl, cb_sidelength, cb_sidelength); EZ_control_SetAnchor(close_ctrl, (anchor_top | anchor_right)); } } // Scrollpane. { window->scrollpane = EZ_scrollpane_Create(tree, window_ctrl, "Window scrollpane", NULL, rh_size, (rh_size + titlebar_ctrl->height), 10, 10, 0); scrollpane_ctrl = (ez_control_t *)window->scrollpane; // Size the scrollpane to fit inside the window control. EZ_control_SetSize(scrollpane_ctrl, (window_ctrl->width - (2 * rh_size)), (window_ctrl->height - (titlebar_ctrl->height + (2 * rh_size)))); EZ_control_SetAnchor(scrollpane_ctrl, (anchor_left | anchor_right | anchor_bottom | anchor_top)); // Window area. { window->window_area = EZ_control_Create(tree, scrollpane_ctrl, "Window area", NULL, 0, 0, 10, 10, (control_scrollable | control_enabled | control_resizeable)); // Set the window area as the target of the scrollpane // (this will make it a child of the scrollpane, so don't bother to add it as a child to the window itself). EZ_scrollpane_SetTarget(window->scrollpane, window->window_area); EZ_control_SetDrawOrder(window->window_area, scrollpane_ctrl->draw_order + 1, true); } } }
// // Button - Recalculates and sets the position of the buttons label. // static void EZ_button_RecalculateLabelPosition(ez_button_t *button) { ez_control_t *self = ((ez_control_t *)button); ez_label_t *label = button->text_label; ez_control_t *text_label_ctrl = ((ez_control_t *)label); // ez_textalign_t alignment = button->text_alignment; int new_x = text_label_ctrl->x; int new_y = text_label_ctrl->y; int new_anchor = EZ_control_GetAnchor(text_label_ctrl); // TODO : Hmm, should we even bothered with a special case for text alignment? Why not just use ez_anchor_t stuff? Also remember to add support for middle_top and such. switch (button->text_alignment) { case top_left : { new_anchor = (anchor_left | anchor_top); new_x = 0; new_y = 0; break; } case top_right : { new_anchor = (anchor_right | anchor_top); new_x = 0; new_y = 0; break; } case top_center : { new_anchor = anchor_top; new_x = Q_rint((self->width - text_label_ctrl->width) / 2.0); new_y = 0; break; } case bottom_left : { new_anchor = (anchor_left | anchor_bottom); new_x = 0; new_y = 0; break; } case bottom_right : { new_anchor = (anchor_right | anchor_bottom); new_x = 0; new_y = 0; break; } case bottom_center : { new_anchor = anchor_bottom; new_x = Q_rint((self->width - text_label_ctrl->width) / 2.0); new_y = 0; break; } case middle_right : { new_anchor = anchor_right; new_x = 0; new_y = Q_rint((self->height - text_label_ctrl->height) / 2.0); break; } case middle_left : { new_anchor = anchor_left; new_x = 0; new_y = Q_rint((self->height - text_label_ctrl->height) / 2.0); break; } case middle_center : { new_anchor = (anchor_left | anchor_top); new_x = Q_rint((self->width - text_label_ctrl->width) / 2.0); new_y = Q_rint((self->height - text_label_ctrl->height) / 2.0); break; } default : break; } if (new_anchor != EZ_control_GetAnchor(text_label_ctrl)) { EZ_control_SetAnchor(text_label_ctrl, new_anchor); } if ((new_x != text_label_ctrl->x) || (new_y != text_label_ctrl->y)) { EZ_control_SetPosition(text_label_ctrl, new_x, new_y); } }