📄 spinbutton.c
字号:
(spin_p->arrow_sensitivity != XmARROWS_RIGHT_SENSITIVE) && (spin_p->arrow_sensitivity != XmARROWS_INSENSITIVE)) { XtWarning(SPIN_ARROW_SENSITIVE); spin_p->arrow_sensitivity = XmARROWS_SENSITIVE; } if ((spin_p->alignment != XmALIGNMENT_CENTER) && (spin_p->alignment != XmALIGNMENT_BEGINNING) && (spin_p->alignment != XmALIGNMENT_END)) { XtWarning(SPIN_ALIGNMENT); spin_p->alignment = XmALIGNMENT_CENTER; } if (spin_p->initial_delay <= 0) { XtWarning(SPIN_INIT_DELAY); spin_p->initial_delay = 250; } if ((spin_p->arrow_layout != XmARROWS_FLAT_BEGINNING) && (spin_p->arrow_layout != XmARROWS_FLAT_END) && (spin_p->arrow_layout != XmARROWS_SPLIT) && (spin_p->arrow_layout != XmARROWS_BEGINNING) && (spin_p->arrow_layout != XmARROWS_END)) { XtWarning(SPIN_ARROW_LAYOUT); spin_p->arrow_layout = XmARROWS_BEGINNING; } if (spin_p->repeat_delay <= 0) { XtWarning(SPIN_REPEAT_DELAY); spin_p->repeat_delay = 200; } if (spin_p->item_count < 0) { XtWarning(SPIN_ITEM_COUNT); spin_p->item_count = 0; } if ((spin_p->child_type == XmSTRING) && ((spin_p->position < 0) || ((spin_p->position >= spin_p->item_count) && (spin_p->item_count > 0)))) { XtWarning(SPIN_POSITION_STRING); spin_p->position = 0; } if ((spin_p->decimal_points < 0) || (spin_p->decimal_points > MAX_FLOAT_DECIMALS)) { XtWarning(SPIN_DECIMAL_POINTS); spin_p->decimal_points = 0; } if (spin_p->minimum > spin_p->maximum) { XtWarning(SPIN_MIN_MAX); spin_p->minimum = spin_p->maximum; } if ((spin_p->child_type == XmNUMERIC) && ((spin_p->position < spin_p->minimum) || (spin_p->position > spin_p->maximum) || ((spin_p->position % spin_p->numeric_increment) != 0))) { XtWarning(SPIN_POSITION_NUMERIC); spin_p->position = spin_p->minimum; }}/* * Destroy procedure called by the toolkit. Remove all callbacks and * event-handlers. */static void Destroy(spin)DtSpinButtonWidget spin;{ DtSpinButtonPart *spin_p = (DtSpinButtonPart*)&(spin->spin_button); int i; if ((int)timer) XtRemoveTimeOut(timer); if (spin_p->items) { for (i = 0; i < spin_p->item_count; i++) { XmStringFree(spin_p->items[i]); } XtFree((char*)spin_p->items); } if (spin_p->text) { XtRemoveCallback(spin_p->text, XmNlosingFocusCallback, text_losing_focus_cb, (XtPointer)spin); XtRemoveCallback(spin_p->text, XmNactivateCallback, text_activate_cb, (XtPointer)spin); XtRemoveCallback(spin_p->text, XmNfocusCallback, text_focus_cb, (XtPointer)spin); } XtRemoveCallback(spin_p->up_arrow, XmNarmCallback, up_cb, (XtPointer)spin); XtRemoveCallback(spin_p->up_arrow, XmNdisarmCallback, disarm_cb, (XtPointer)spin); XtRemoveEventHandler(spin_p->up_arrow, LeaveWindowMask, FALSE, grab_leave_cb, (XtPointer)spin); XtRemoveCallback(spin_p->down_arrow, XmNarmCallback, down_cb, (XtPointer)spin); XtRemoveCallback(spin_p->down_arrow, XmNdisarmCallback, disarm_cb, (XtPointer)spin); XtRemoveEventHandler(spin_p->down_arrow, LeaveWindowMask, FALSE, grab_leave_cb, (XtPointer)spin);}/* * Resize function called by toolkit. The size of our spin-box * has already been changed. That is why we must store * old_width and old_height. */static voidResize(spin)DtSpinButtonWidget spin;{ DtSpinButtonPart *spin_p = (DtSpinButtonPart*)&(spin->spin_button); ClearShadow(spin, TRUE); LayoutChildren(spin); DrawShadow(spin); spin_p->old_width = spin->core.width; spin_p->old_height = spin->core.height;}/* * Redisplay function called by toolkit. The widget didn't change size, * so just redisplay the shadow. */static voidRedisplay(w, event, region)DtSpinButtonWidget w;XEvent *event;Region region;{ DrawShadow(w, SPIN_MARGIN_W(w), SPIN_MARGIN_H(w), SPIN_SHADOW(w));}/* * GeometryManager function called by toolkit when a child resizes/moves. * We are not allowing any changes but width/height of the text-field. * this is because the user can retrieve the text-field and make changes * that we want to honor. If they mess around with the label or arrow, * then we won't honor the request. * If the text-field requests a change, then make the change, and allow * our SetSpinButtonSize() and LayoutChildren() figure out what size will * be allowed. * Returning GeometryDone was suppose to tell the toolkit * that we resized the child ourselves, but the text-field had trouble * with this (its' geometry_manager wasn't called or working right?), so * we return GeometryYes. */static XtGeometryResultGeometryManager(w, request, reply)Widget w; /* child */XtWidgetGeometry *request;XtWidgetGeometry *reply;{ DtSpinButtonWidget spin = (DtSpinButtonWidget)(w->core.parent); /* Ignore everything but text-field */ if (w != spin->spin_button.text) return(XtGeometryNo); /* Only allow width/height changes */ if (!(request->request_mode & (CWWidth | CWHeight))) return(XtGeometryNo); /* Set the text-field to the requested size */ if (request->request_mode & CWWidth) w->core.width = request->width; if (request->request_mode & CWHeight) w->core.height = request->height; XtResizeWidget(w, w->core.width, w->core.height, w->core.border_width); ClearShadow(spin, TRUE); if (spin->spin_button.recompute_size) SetSpinButtonSize(spin); LayoutChildren(spin); DrawShadow(spin); return(XtGeometryYes);}/* * This function sets the size of the spin_button widget based on the * current size of the children. Don't worry if it doesn't work, the * children will be squeezed in later. */static voidSetSpinButtonSize(spin)DtSpinButtonWidget spin;{ DtSpinButtonPart *spin_p = (DtSpinButtonPart*)&(spin->spin_button); Widget text_holder = spin_p->editable ? spin_p->text : spin_p->label; Dimension shadow = SPIN_SHADOW(spin) * 2; short arrow_width, arrow_height; short height = text_holder->core.height; /* * Find out how big the arrow can be (needed to get * available_width for text_holder). */ arrow_width = (Dimension)(text_holder->core.height * ARROW_MULT); arrow_width = (arrow_width < ARROW_MIN) ? ARROW_MIN : arrow_width; /* Get height based on arrow width */ arrow_height = arrow_width; if ((spin_p->arrow_layout == XmARROWS_BEGINNING) || (spin_p->arrow_layout == XmARROWS_END)) arrow_height += arrow_height; /* Make height bigger of 2 - arrows vs text_holder */ if (arrow_height > (short)text_holder->core.height) height = arrow_height; /* If not stacked add extra width for arrows */ if ((spin_p->arrow_layout != XmARROWS_BEGINNING) && (spin_p->arrow_layout != XmARROWS_END)) { arrow_width += arrow_width; } (void)XtMakeResizeRequest((Widget)spin, arrow_width + text_holder->core.width + shadow + (SPIN_MARGIN_W(spin) * 2), height + shadow + (SPIN_MARGIN_H(spin) * 2), NULL, NULL); spin_p->old_width = spin->core.width; spin_p->old_height = spin->core.height;}/* * This function makes the text_holder (label or text-field) smaller * if the spin_button couldn't grow to the needed full size. It will * also make the text_holder grow if there is space. The textfield will * grow with the spin_button, but the label will only grow to its' * maximum size. The label will also shrink down to nothing, but the * text-field will always keep its' core height. */static voidForceChildSizes(spin)DtSpinButtonWidget spin;{ DtSpinButtonPart *spin_p = (DtSpinButtonPart*)&(spin->spin_button); short available_height, available_width; short arrow_width; /* Calculate available height for children */ if ((available_height = spin->core.height - (SPIN_SHADOW(spin) * 2) - (SPIN_MARGIN_H(spin) * 2)) <= 0) available_height = 1; /* Get initial available width for children */ available_width = (spin->core.width - (SPIN_SHADOW(spin) * 2) - (SPIN_MARGIN_W(spin) * 2)); /* label only grows to maximum width needed */ if ((spin_p->editable == FALSE) && (available_height > (short)spin_p->label_max_height)) available_height = spin_p->label_max_height; else if (spin_p->editable) available_height = spin_p->text->core.height; /* * Find out how big the arrow can be (needed to get * available_width for text_holder). */ arrow_width = (Dimension)(available_height * ARROW_MULT); arrow_width = (arrow_width < ARROW_MIN) ? ARROW_MIN : arrow_width; /* Make sure width isn't too small or too big */ if ((available_width -= arrow_width) <= 0) available_width = 1; /* If not stacked subtract extra arrow */ if ((spin_p->arrow_layout != XmARROWS_BEGINNING) && (spin_p->arrow_layout != XmARROWS_END)) { available_width -= arrow_width; } if (spin_p->editable == FALSE) { /** label **/ if (available_width > (short)spin_p->label_max_length) available_width = spin_p->label_max_length; if ((available_width != spin_p->label->core.width) || (available_height != spin_p->label->core.height)) XtResizeWidget(spin_p->label, available_width, available_height, spin_p->label->core.border_width); } else if (spin_p->text->core.width != available_width) /** TextField **/ XtResizeWidget(spin_p->text, available_width, spin_p->text->core.height, spin_p->text->core.border_width); if ((arrow_width != spin_p->up_arrow->core.width) || (spin_p->up_arrow->core.height != arrow_width)) { available_height = (available_height < ARROW_MIN) ? ARROW_MIN : available_height; XtResizeWidget(spin_p->up_arrow, arrow_width, arrow_width, spin_p->up_arrow->core.border_width); } if ((arrow_width != spin_p->down_arrow->core.width) || (spin_p->down_arrow->core.height != arrow_width)) { available_height = (available_height < ARROW_MIN) ? ARROW_MIN : available_height; XtResizeWidget(spin_p->down_arrow, arrow_width, arrow_width, spin_p->down_arrow->core.border_width); }}/* * This function positions the children within the spin_button widget. * It calls ForceChildSizes() to make sure the children fit within the * spin_button widget, but it will not try to resize the spin_button widget. */static voidLayoutChildren(spin)DtSpinButtonWidget spin;{ DtSpinButtonPart *spin_p = (DtSpinButtonPart*)&(spin->spin_button); Widget text_holder = spin_p->editable ? spin_p->text : spin_p->label; Position start_x = SPIN_SHADOW(spin) + SPIN_MARGIN_W(spin); Position start_y = SPIN_SHADOW(spin) + SPIN_MARGIN_H(spin); short available_height = spin->core.height - (start_y * 2); Position y, arrow_y; Dimension arrow_height; ForceChildSizes(spin); /* Center text_holder within spin_button */ y = available_height - text_holder->core.height; y = ((y < 0) ? 0 : y)/2 + start_y; arrow_height = spin_p->up_arrow->core.height; if ((spin_p->arrow_layout == XmARROWS_BEGINNING) || (spin_p->arrow_layout == XmARROWS_END)) arrow_height += arrow_height; arrow_y = available_height - arrow_height; arrow_y = ((arrow_y < 0) ? 0 : arrow_y)/2 + start_y; switch (spin_p->arrow_layout) { case XmARROWS_FLAT_BEGINNING: XtMoveWidget(spin_p->up_arrow, start_x, arrow_y); start_x += spin_p->up_arrow->core.width; XtMoveWidget(spin_p->down_arrow, start_x, arrow_y); start_x += spin_p->down_arrow->core.width; XtMoveWidget(text_holder, start_x, y); break; case XmARROWS_FLAT_END: XtMoveWidget(text_holder, start_x, y); /* * This start_x places arrow right after text_holder. With * labels we want the arrow at the end of the spin_button, so * the user can use recompute_size more effectively. * start_x += text_holder->core.width; */ start_x = (spin->core.width - start_x - spin_p->up_arrow->core.width - spin_p->down_arrow->core.width); XtMoveWidget(spin_p->up_arrow, start_x, arrow_y); start_x += spin_p->up_arrow->core.width; XtMoveWidget(spin_p->down_arrow, start_x, arrow_y); break; case XmARROWS_SPLIT: XtMoveWidget(spin_p->down_arrow, start_x, arrow_y); start_x += spin_p->down_arrow->core.width; XtMoveWidget(text_holder, start_x, y); start_x += text_holder->core.width; XtMoveWidget(spin_p->up_arrow, start_x, arrow_y); break; case XmARROWS_BEGINNING: XtMoveWidget(spin_p->up_arrow, start_x, arrow_y); arrow_y += spin_p->up_arrow->core.height; XtMoveWidget(spin_p->down_arrow, start_x, arrow_y); start_x += spin_p->down_arrow->core.width; XtMoveWidget(text_holder, start_x, y); break; case XmARROWS_END: XtMoveWidget(text_holder, start_x, y); /* * This start_x places arrow right after text_holder. With * labels we want the arrow at the end of the spin_button, so * the user can use recompute_size more effectively. * start_x += text_holder->core.width; */ start_x = spin->core.width - start_x - spin_p->up_arrow->core.width; XtMoveWidget(spin_p->up_arrow, start_x, arrow_y); arrow_y += spin_p->up_arrow->core.width; XtMoveWidget(spin_p->down_arrow, start_x, arrow_y);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -