/** * @brief Sets the submenu of the menu-item: the submenu will be popped up when the menu-item is selected * @param menu_item a menu-item * @param submenu the submenu to attach to the menu-item */ void etk_menu_item_submenu_set(Etk_Menu_Item *menu_item, Etk_Menu *submenu) { if (!menu_item || menu_item->submenu == submenu) return; if (menu_item->submenu) { menu_item->submenu->parent_item = NULL; etk_object_notify(ETK_OBJECT(menu_item->submenu), "parent-item"); } menu_item->submenu = submenu; if (menu_item->submenu) { menu_item->submenu->parent_item = menu_item; etk_object_notify(ETK_OBJECT(menu_item->submenu), "parent-item"); } if (menu_item->submenu) etk_widget_theme_signal_emit(ETK_WIDGET(menu_item), "etk,action,show,arrow", ETK_TRUE); else etk_widget_theme_signal_emit(ETK_WIDGET(menu_item), "etk,action,hide,arrow", ETK_TRUE); etk_widget_size_recalc_queue(ETK_WIDGET(menu_item)); etk_object_notify(ETK_OBJECT(menu_item), "submenu"); }
/** * @brief Sets the label of the frame * @param frame a frame * @param label the label to set */ void etk_frame_label_set(Etk_Frame *frame, const char *label) { if (!frame) return; if (label != frame->label) { free(frame->label); frame->label = label ? strdup(label) : NULL; } if (!frame->label || frame->label[0] == '\0') { etk_widget_theme_part_text_set(ETK_WIDGET(frame), "etk.text.label", ""); etk_widget_theme_signal_emit(ETK_WIDGET(frame), "etk,action,hide,label", ETK_TRUE); } else { etk_widget_theme_part_text_set(ETK_WIDGET(frame), "etk.text.label", frame->label); etk_widget_theme_signal_emit(ETK_WIDGET(frame), "etk,action,show,label", ETK_TRUE); } if (label != frame->label) etk_object_notify(ETK_OBJECT(frame), "label"); }
/** * @brief Inserts a character into a string, at a given position * @param string a string. If @a string is NULL, a new string is created * @param pos the position where to insert the char * @param c the character to insert into the string * @return Returns the string */ Etk_String *etk_string_insert_char(Etk_String *string, int pos, char c) { int i; if (!string) return etk_string_insert_char(etk_string_new(NULL), pos, c); if (c == '\0') return etk_string_truncate(string, pos); pos = ETK_CLAMP(pos, 0, string->length); if (string->length + 1 > string->allocated_length) { string->string = realloc(string->string, SIZE_TO_ALLOC(string->length + 1) + 1); string->allocated_length = SIZE_TO_ALLOC(string->length + 1); } for (i = string->length - 1; i >= pos; i--) string->string[i + 1] = string->string[i]; string->string[pos] = c; string->length++; string->string[string->length] = '\0'; etk_object_notify(ETK_OBJECT(string), "string"); return string; }
/** * @brief Sets the group of the radio-button * @param radio_button a radio-button * @param group the group to use */ void etk_radio_button_group_set(Etk_Radio_Button *radio_button, Eina_List **group) { Etk_Toggle_Button *toggle_button; Etk_Bool active; if (!(toggle_button = ETK_TOGGLE_BUTTON(radio_button)) || (group && (radio_button->group == group))) return; if (radio_button->group) { *radio_button->group = eina_list_remove(*radio_button->group, radio_button); if (!(*radio_button->group)) { free(radio_button->group); radio_button->group = NULL; } } if (!group) { group = malloc(sizeof(Eina_List *)); *group = NULL; active = ETK_TRUE; } else active = ETK_FALSE; *group = eina_list_append(*group, radio_button); radio_button->group = group; etk_object_notify(ETK_OBJECT(radio_button), "group"); radio_button->can_uncheck = ETK_TRUE; etk_toggle_button_active_set(toggle_button, active); }
/* This function is called when the radio-button is turned on: it deactivates all * the other radio-buttons of the group, and activate the given radio-button */ static void _etk_radio_button_active_set(Etk_Toggle_Button *toggle_button, Etk_Bool active) { Etk_Radio_Button *radio_button; Etk_Toggle_Button *tb; Eina_List *l; if (!(radio_button = ETK_RADIO_BUTTON(toggle_button)) || toggle_button->active == active) return; if (!toggle_button->active || (toggle_button->active && radio_button->can_uncheck)) { toggle_button->active = active; etk_signal_emit(ETK_TOGGLE_BUTTON_TOGGLED_SIGNAL, ETK_OBJECT(toggle_button)); etk_object_notify(ETK_OBJECT(toggle_button), "active"); if (toggle_button->active) { /* Deactivate the current active button of the group */ for (l = *radio_button->group; l; l = l->next) { tb = ETK_TOGGLE_BUTTON(l->data); if (tb != toggle_button && tb->active) { ETK_RADIO_BUTTON(tb)->can_uncheck = ETK_TRUE; etk_toggle_button_active_set(tb, ETK_FALSE); } } } radio_button->can_uncheck = ETK_FALSE; } }
/** * @brief Sets the group of the radio menu-item * @param radio_item a radio menu-item * @param group the group to set */ void etk_menu_item_radio_group_set(Etk_Menu_Item_Radio *radio_item, Eina_List **group) { Etk_Menu_Item_Check *check_item; Etk_Bool active; if (!(check_item = ETK_MENU_ITEM_CHECK(radio_item)) || (group && (radio_item->group == group))) return; if (radio_item->group) { *radio_item->group = eina_list_remove(*radio_item->group, radio_item); if (!(*radio_item->group)) { free(radio_item->group); radio_item->group = NULL; } } if (!group) { group = malloc(sizeof(Eina_List *)); *group = NULL; active = ETK_TRUE; } else active = ETK_FALSE; *group = eina_list_append(*group, radio_item); radio_item->group = group; etk_object_notify(ETK_OBJECT(radio_item), "group"); radio_item->can_uncheck = ETK_TRUE; etk_menu_item_check_active_set(check_item, active); }
/* Behavior of the "active_set" function for a radio menu item */ static void _etk_menu_item_radio_active_set(Etk_Menu_Item_Check *check_item, Etk_Bool active) { Etk_Menu_Item_Radio *radio_item; Etk_Menu_Item_Check *ci; Eina_List *l; if (!(radio_item = ETK_MENU_ITEM_RADIO(check_item)) || check_item->active == active) return; if (!check_item->active || (check_item->active && radio_item->can_uncheck)) { check_item->active = active; etk_signal_emit(ETK_MENU_ITEM_CHECK_TOGGLED_SIGNAL, ETK_OBJECT(check_item)); etk_object_notify(ETK_OBJECT(check_item), "active"); if (check_item->active) { /* Uncheck the previously checked item of the group */ for (l = *radio_item->group; l; l = l->next) { ci = ETK_MENU_ITEM_CHECK(l->data); if (ci != check_item && ci->active) { ETK_MENU_ITEM_RADIO(ci)->can_uncheck = ETK_TRUE; etk_menu_item_check_active_set(ci, ETK_FALSE); } } } radio_item->can_uncheck = ETK_FALSE; } }
/** * @brief Sets whether or not the action-area's hbox is homogeneous, i.e whether or not all the widgets of the * action-area should have the same size * @param dialog a dialog * @param homogeneous ETK_TRUE to make the action-area's hbox homogeneous, ETK_FALSE otherwise */ void etk_dialog_action_area_homogeneous_set(Etk_Dialog *dialog, Etk_Bool homogeneous) { if (!dialog) return; etk_box_homogeneous_set(ETK_BOX(dialog->action_area_hbox), homogeneous); etk_object_notify(ETK_OBJECT(dialog), "action-area-homogeneous"); }
/** * @brief Sets the horizontal alignment of the widget in the dialog's action-area * @param dialog a dialog * @param align the horizontal alignment (0.0 = left, 0.5 = center, 1.0 = right, ...) */ void etk_dialog_action_area_alignment_set(Etk_Dialog *dialog, float align) { if (!dialog) return; etk_alignment_set(ETK_ALIGNMENT(dialog->action_area_alignment), align, 0.5, 0.0, 0.0); etk_object_notify(ETK_OBJECT(dialog), "action-area-align"); }
/** * @brief Sets whether or not the spinner's value should wrap around to the opposite limit when the value exceed one * of the spinner's bounds * @param spinner a spinner * @param wrap ETK_TRUE to make the value wrap around, ETK_FALSE otherwise */ void etk_spinner_wrap_set(Etk_Spinner *spinner, Etk_Bool wrap) { if (!spinner || spinner->wrap == wrap) return; spinner->wrap = wrap; etk_object_notify(ETK_OBJECT(spinner), "wrap"); }
/** * @brief Sets the amount of free space between two cells * @param box a box * @param spacing the new amount of free space between two cells, in pixels */ void etk_box_spacing_set(Etk_Box *box, int spacing) { if (!box) return; box->spacing = spacing; etk_widget_size_recalc_queue(ETK_WIDGET(box)); etk_object_notify(ETK_OBJECT(box), "spacing"); }
/* Behavior of the "active_set" function for a check menu item */ static void _etk_menu_item_check_active_set(Etk_Menu_Item_Check *check_item, Etk_Bool active) { if (!check_item || check_item->active == active) return; check_item->active = active; etk_signal_emit(ETK_MENU_ITEM_CHECK_TOGGLED_SIGNAL, ETK_OBJECT(check_item)); etk_object_notify(ETK_OBJECT(check_item), "active"); }
/** * @brief Sets whether or not all the cells of the box should have the same size * @param box a box * @param homogeneous if @a homogeneous is ETK_TRUE, all the cells will have the same size */ void etk_box_homogeneous_set(Etk_Box *box, Etk_Bool homogeneous) { if (!box) return; box->homogeneous = homogeneous; etk_widget_size_recalc_queue(ETK_WIDGET(box)); etk_object_notify(ETK_OBJECT(box), "homogeneous"); }
/** * @brief Changes the homogenous property of the table * @param table a table * @param homogeneous a flag describing whether the table should be homogenous horizontally, vertically, * in both directions or not at all */ void etk_table_homogeneous_set(Etk_Table *table, Etk_Table_Homogeneous homogeneous) { if (!table) return; table->homogeneous = homogeneous; etk_widget_size_recalc_queue(ETK_WIDGET(table)); etk_object_notify(ETK_OBJECT(table), "homogeneous"); }
/** * @brief Sets the label of the menu-item * @param menu_item a menu-item * @param label the label to set */ void etk_menu_item_label_set(Etk_Menu_Item *menu_item, const char *label) { if (!menu_item || menu_item->label == label) return; free(menu_item->label); menu_item->label = label ? strdup(label) : NULL; etk_widget_theme_part_text_set(ETK_WIDGET(menu_item), "etk.text.label", label ? label : ""); etk_object_notify(ETK_OBJECT(menu_item), "label"); }
/** * @brief Sets the number of digits displayed by the spinner * @param spinner a spinner * @param digits the number of digits to display */ void etk_spinner_digits_set(Etk_Spinner *spinner, int digits) { if (!spinner || spinner->digits == digits) return; spinner->digits = ETK_MAX(0, digits); snprintf(spinner->value_format, 16, "%%.%df", spinner->digits); _etk_spinner_update_text_from_value(spinner); etk_object_notify(ETK_OBJECT(spinner), "digits"); }
/** * @brief Sets whether the statusbar has a resize-grip. The resize-grip is a small grip at the right of the statusbar * that the user can use to resize the window * @param statusbar a statusbar * @param has_resize_grip if @a has_resize_grip is ETK_TRUE to make the statusbar have a resize-grip */ void etk_statusbar_has_resize_grip_set(Etk_Statusbar *statusbar, Etk_Bool has_resize_grip) { if (!statusbar || statusbar->has_resize_grip == has_resize_grip) return; statusbar->has_resize_grip = has_resize_grip; if (statusbar->has_resize_grip) etk_widget_theme_signal_emit(ETK_WIDGET(statusbar), "etk,action,show,resize_grip", ETK_TRUE); else etk_widget_theme_signal_emit(ETK_WIDGET(statusbar), "etk,action,hide,resize_grip", ETK_TRUE); etk_object_notify(ETK_OBJECT(statusbar), "has-resize-grip"); }
/** * @brief Sets whether or not there is a horizontal separator between the main-area and the action-area of the dialog * @param dialog a dialog * @param has_separator ETK_TRUE to make the separator visible, ETK_FALSE to hide it */ void etk_dialog_has_separator_set(Etk_Dialog *dialog, Etk_Bool has_separator) { if (!dialog || dialog->has_separator == has_separator) return; if (has_separator) etk_widget_show(dialog->separator); else etk_widget_hide(dialog->separator); dialog->has_separator = has_separator; etk_object_notify(ETK_OBJECT(dialog), "has-separator"); }
/** * @brief Truncates the string * @param string a string * @param length the new length of the string. If @a length is greater than * the current length of the string, the function does nothing * @return Returns the truncated string */ Etk_String *etk_string_truncate(Etk_String *string, int length) { if (!string || length < 0) return NULL; if (length < string->length) { string->string[length] = '\0'; string->length = length; etk_object_notify(ETK_OBJECT(string), "string"); } return string; }
/** * @brief Sets whether or not the value of the spinner should be automatically * corrected to the nearest step-increment * @param spinner a spinner * @param snap_to_ticks ETK_TRUE if you want the value to be corrected, ETK_FALSE otherwise */ void etk_spinner_snap_to_ticks_set(Etk_Spinner *spinner, Etk_Bool snap_to_ticks) { if (!spinner || spinner->snap_to_ticks == snap_to_ticks) return; spinner->snap_to_ticks = snap_to_ticks; if (snap_to_ticks) { double new_value; new_value = _etk_spinner_value_snap(spinner, etk_range_value_get(ETK_RANGE(spinner))); etk_range_value_set(ETK_RANGE(spinner), new_value); } etk_object_notify(ETK_OBJECT(spinner), "snap-to-ticks"); }
/** * @brief Pushs a new message on the statusbar's message-stack * @param statusbar a statusbar * @param message the message to push * @param context_id the context-id to associate to the message. * You can generate a context-id with @a etk_statusbar_context_id_get() * @return Returns the message-id of the message, or -1 on failure */ int etk_statusbar_message_push(Etk_Statusbar *statusbar, const char *message, int context_id) { Etk_Statusbar_Msg *new_msg; if (!statusbar || !message) return -1; new_msg = malloc(sizeof(Etk_Statusbar_Msg)); new_msg->msg = strdup(message); new_msg->context_id = context_id; new_msg->message_id = statusbar->next_message_id++; statusbar->msg_stack = eina_list_prepend(statusbar->msg_stack, new_msg); _etk_statusbar_update(statusbar); etk_object_notify(ETK_OBJECT(statusbar), "current-message"); return new_msg->message_id; }
/** * @brief Sets the stock-size of the toolbar's tool-buttons * @param toolbar a toolbar * @param size the stock-size to use */ void etk_toolbar_stock_size_set(Etk_Toolbar *toolbar, Etk_Stock_Size size) { Eina_List *children, *l; if (!toolbar || toolbar->stock_size == size) return; toolbar->stock_size = size; children = etk_container_children_get(ETK_CONTAINER(toolbar->box)); for (l = children; l; l = l->next) { if (ETK_IS_TOOL_ITEM(l->data)) etk_button_stock_size_set(ETK_BUTTON(l->data), size); } eina_list_free(children); etk_object_notify(ETK_OBJECT(toolbar), "stock-size"); }
/** * @brief Removes the message corresponding to the message-id from the statusbar * @param statusbar a statusbar * @param message_id the message-id of the message to remove. It has been returned * when you pushed the message with @a etk_statusbar_push() */ void etk_statusbar_message_remove(Etk_Statusbar *statusbar, int message_id) { Eina_List *l; Etk_Statusbar_Msg *m; if (!statusbar) return; for (l = statusbar->msg_stack; l; l = l->next) { m = l->data; if (m->message_id == message_id) { free(m->msg); free(m); statusbar->msg_stack = eina_list_remove_list(statusbar->msg_stack, l); _etk_statusbar_update(statusbar); etk_object_notify(ETK_OBJECT(statusbar), "current-message"); break; } } }
/** * @brief Sets the style of toolbar's tool-buttons (icon, text, both vertically, both horizontally) * @param toolbar a toolbar * @param style the style to set */ void etk_toolbar_style_set(Etk_Toolbar *toolbar, Etk_Toolbar_Style style) { Eina_List *children, *l; Etk_Button_Style button_style; if (!toolbar || toolbar->style == style) return; toolbar->style = style; switch (style) { case ETK_TOOLBAR_ICON: button_style = ETK_BUTTON_ICON; break; case ETK_TOOLBAR_TEXT: button_style = ETK_BUTTON_TEXT; break; case ETK_TOOLBAR_BOTH_VERT: button_style = ETK_BUTTON_BOTH_VERT; break; case ETK_TOOLBAR_BOTH_HORIZ: button_style = ETK_BUTTON_BOTH_HORIZ; break; default: button_style = ETK_BUTTON_BOTH_VERT; break; } children = etk_container_children_get(ETK_CONTAINER(toolbar->box)); for (l = children; l; l = l->next) { if (ETK_IS_TOOL_ITEM(l->data)) etk_button_style_set(ETK_BUTTON(l->data), button_style); } eina_list_free(children); etk_object_notify(ETK_OBJECT(toolbar), "style"); }
/** * @brief Inserts a text with a specific length into a string, at a given position * @param string a string. If @a string is NULL, a new string is created * @param pos the position where to insert the text (starting from 0) * @param text the text to insert into the string * @param length the maximum length of the text to insert * @return Returns the string */ Etk_String *etk_string_insert_sized(Etk_String *string, int pos, const char *text, int length) { if (!string) return etk_string_new_sized(text, length); if (!text || text[0] == '\0' || length <= 0) return string; pos = ETK_CLAMP(pos, 0, string->length); length = _etk_string_strlen_max(text, length); if (string->length + length > string->allocated_length) { string->string = realloc(string->string, SIZE_TO_ALLOC(string->length + length) + 1); string->allocated_length = SIZE_TO_ALLOC(string->length + length); } memmove(&string->string[pos + length], &string->string[pos], string->length - pos); strncpy(&string->string[pos], text, length); string->length += length; string->string[string->length] = '\0'; etk_object_notify(ETK_OBJECT(string), "string"); return string; }
/** * @brief Sets the toolbar's orientation (horizontal or vertical) * @param toolbar a toolbar * @param orientation the orientation to set */ void etk_toolbar_orientation_set(Etk_Toolbar *toolbar, Etk_Toolbar_Orientation orientation) { Eina_List *children, *l; Etk_Widget *prev_box; if (!toolbar || toolbar->orientation == orientation) return; toolbar->reorientating = ETK_TRUE; prev_box = toolbar->box; toolbar->orientation = orientation; if (toolbar->orientation == ETK_TOOLBAR_VERT) toolbar->box = etk_vbox_new(ETK_FALSE, 0); else toolbar->box = etk_hbox_new(ETK_FALSE, 0); etk_widget_internal_set(toolbar->box, ETK_TRUE); etk_widget_show(toolbar->box); etk_signal_connect_by_code(ETK_CONTAINER_CHILD_ADDED_SIGNAL, ETK_OBJECT(toolbar->box), ETK_CALLBACK(_etk_toolbar_child_added_cb), toolbar); etk_signal_connect_by_code(ETK_CONTAINER_CHILD_REMOVED_SIGNAL, ETK_OBJECT(toolbar->box), ETK_CALLBACK(_etk_toolbar_child_removed_cb), NULL); children = etk_container_children_get(ETK_CONTAINER(prev_box)); for (l = children; l; l = l->next) etk_toolbar_append(toolbar, ETK_WIDGET(l->data), ETK_BOX_START); eina_list_free(children); etk_object_destroy(ETK_OBJECT(prev_box)); if (toolbar->orientation == ETK_TOOLBAR_VERT) etk_widget_theme_group_set(ETK_WIDGET(toolbar), "vtoolbar"); else etk_widget_theme_group_set(ETK_WIDGET(toolbar), "htoolbar"); etk_widget_parent_set(toolbar->box, ETK_WIDGET(toolbar)); toolbar->reorientating = ETK_FALSE; etk_object_notify(ETK_OBJECT(toolbar), "orientation"); }
/** * @brief Sets the value of a string, with a specific size. * @param string a string. If @a string is NULL, a new string is created * @param value the value to assign to the string * @param size If @a size is lower than the length of @a value, the value will be truncated. * Otherwise, if @a size is greater than the length of @a value, extra memory will be allocated. * It may be useful if you plan to often insert text and want to avoid too many reallocations. * @return Returns the string */ Etk_String *etk_string_set_sized(Etk_String *string, const char *value, int size) { if (!string) return etk_string_new_sized(value, size); if (!value || value[0] == '\0' || size <= 0) return etk_string_clear(string); else { if (size > string->allocated_length) { free(string->string); string->string = malloc(SIZE_TO_ALLOC(size) + 1); string->allocated_length = SIZE_TO_ALLOC(size); } string->length = _etk_string_strlen_max(value, size); strncpy(string->string, value, string->length); string->string[string->length] = '\0'; } etk_object_notify(ETK_OBJECT(string), "string"); return string; }
/** * @brief Resizes the table. The children that are attached to a row or a column that is removed will be unparented * @param table a table * @param num_rows the new number of rows * @param num_cols the new number of cols */ void etk_table_resize(Etk_Table *table, int num_cols, int num_rows) { Eina_List *l, *next; Etk_Table_Cell **new_cells; Etk_Table_Cell *cell; Etk_Table_Col_Row *new_cols, *new_rows; Etk_Widget *child; int i, j; if (!table) return; if (num_cols < 0) num_cols = 0; if (num_rows < 0) num_rows = 0; if (num_cols == 0 && num_rows == 0) { new_cells = NULL; new_cols = NULL; new_rows = NULL; } else { new_cells = calloc(num_cols * num_rows, sizeof(Etk_Table_Cell *)); new_cols = malloc(num_cols * sizeof(Etk_Table_Col_Row)); new_rows = malloc(num_rows * sizeof(Etk_Table_Col_Row)); } for (l = table->cells_list; l; l = next) { next = l->next; cell = l->data; child = cell->child; /* The child is in the old table but not in the new one: we remove it */ if (cell->left_attach >= num_cols || cell->top_attach >= num_rows) etk_table_cell_clear(table, cell->left_attach, cell->top_attach); /* The child is in the new table: we copy it to the new table */ else { cell->right_attach = ETK_MIN(num_cols - 1, cell->right_attach); cell->bottom_attach = ETK_MIN(num_rows - 1, cell->bottom_attach); for (i = cell->left_attach; i <= cell->right_attach; i++) { for (j = cell->top_attach; j <= cell->bottom_attach; j++) new_cells[j * num_cols + i] = cell; } } } free(table->cells); free(table->cols); free(table->rows); table->cells = new_cells; table->cols = new_cols; table->rows = new_rows; table->num_cols = num_cols; table->num_rows = num_rows; etk_widget_size_recalc_queue(ETK_WIDGET(table)); etk_object_notify(ETK_OBJECT(table), "num-cols"); etk_object_notify(ETK_OBJECT(table), "num-rows"); }