/* Project CADshell Mechanical Design Research Lab Mechanical Engineering - Engineering Mechanics Dept. Michigan Technological University Copyright (C) 2001. All Rights Reserved. FILE: controls.cc MODULE: CADshell REQUIRES LIBRARIES: libXm, libXt, libX11 AUTHOR(S): Bernie Bettig OVERVIEW ======== Source for sh_MessageBox, sh_Control, sh_CompositeControl (sh_Control), sh_Form (sh_CompositeControl), sh_FramedControl (sh_CompositeControl), sh_Dialog (sh_FramedControl), sh_FileDialog (sh_FramedControl), sh_Button (sh_Control), sh_OnOffButton (sh_Button), sh_OkButton (sh_Button), sh_CancelButton (sh_Button), sh_ApplyButton (sh_Button), sh_OkApplyCancel (sh_Form), sh_CheckBox (sh_Control), sh_Label (sh_Control), sh_LabeledControl (sh_Form), sh_TextInput (sh_Control), sh_TextInput_DynAlloc (sh_Control), sh_TextListInput (sh_Control), sh_OptionSelect (sh_Control), sh_IntInput (sh_Control), sh_DoubleInput (sh_Control), sh_DoubleInputWithUnits (sh_Control), sh_ExpressionInput (sh_Control), sh_Slider (sh_Control), sh_Scrollbar (sh_Control), sh_Vec3fInput (sh_Dialog), */ #include "controls.h" #include "controls_main.h" #include #if defined (CADSHELL) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(CADSHELL) /* -------------------------------------------------------------------------------------- sh_EventHandler -------------------------------------------------------------------------------------- */ void sh_EventHandler::PointerEvent(sh_Viewer *, int, int, unsigned int, unsigned int) {} void sh_EventHandler::PointerEvent3d(sh_Viewer *, int, int, sh_Point&) {} void sh_EventHandler::KeyboardEvent(sh_Viewer *, int, int, unsigned int) {} void sh_EventHandler::KeyPressed(sh_Viewer *, char ) {} sh_Control *sh_EventHandler::GetMenuButton(sh_CompositeControl *, const char *, char) { return 0; } sh_Control *sh_EventHandler::GetControlBarButton(sh_CompositeControl *, const char *) { return 0; } #endif /* -------------------------------------------------------------------------------------- sh_MessageBox -------------------------------------------------------------------------------------- */ int sh_MessageBox::Message(const char *message, const char *title, int flags) { int reply; sh_MessageBox m(message, title, flags); reply = m.Execute(); return reply; } sh_MessageBox::sh_MessageBox(const char *message, const char *name, int flags) { Widget button; int buttons, icons; void MBunmap(Widget w, XtPointer userData, XtPointer callbackData); void MBOk(Widget w, XtPointer userData, XtPointer callbackData); void MBCancel(Widget w, XtPointer userData, XtPointer callbackData); void MBYes(Widget w, XtPointer userData, XtPointer callbackData); void MBNo(Widget w, XtPointer userData, XtPointer callbackData); XmString title, text; Arg args[3]; int n = 0; buttons = flags & 496; icons = flags & 15; if (!buttons) buttons = MB_OK; autoDelete = true; if (!name) #ifdef CADSHELL name = sh_CADshell::GetShell()->GetName(); #else name = "Error"; #endif title = XmStringCreateSimple((char *)name); text = XmStringCreateSimple((char *)message); XtSetArg(args[0], XmNdialogTitle, title); n++; XtSetArg(args[1], XmNmessageString, text); n++; XtSetArg(args[2], XmNautoUnmanage, false); n++; dialogWidget = XmCreateWarningDialog(sh_MainWindow::GetMainWindow()->GetTopWidget(), (char*)"sh_MessageBox", args, n); XtAddCallback(dialogWidget, XmNunmapCallback, MBunmap, this); XtAddCallback(dialogWidget, XmNokCallback, MBOk, this); XtAddCallback(dialogWidget, XmNcancelCallback, MBCancel, this); XmStringFree(title); XmStringFree(text); switch (icons) { case MB_ICONERROR: XtVaSetValues(dialogWidget, XmNdialogType, XmDIALOG_ERROR, NULL); break; case MB_ICONINFORMATION: XtVaSetValues(dialogWidget, XmNdialogType, XmDIALOG_INFORMATION, NULL); break; case MB_ICONMESSAGE: XtVaSetValues(dialogWidget, XmNdialogType, XmDIALOG_MESSAGE, NULL); break; case MB_ICONQUESTION: XtVaSetValues(dialogWidget, XmNdialogType, XmDIALOG_QUESTION, NULL); break; case MB_ICONTEMPLATE: XtVaSetValues(dialogWidget, XmNdialogType, XmDIALOG_TEMPLATE, NULL); break; case MB_ICONWARNING: XtVaSetValues(dialogWidget, XmNdialogType, XmDIALOG_WARNING, NULL); break; case MB_ICONWORKING: XtVaSetValues(dialogWidget, XmNdialogType, XmDIALOG_WORKING, NULL); break; } if (!(buttons & MB_OK)) { button = XmMessageBoxGetChild(dialogWidget, XmDIALOG_OK_BUTTON); XtUnmanageChild(button); } if (!(buttons & MB_CANCEL)) { button = XmMessageBoxGetChild(dialogWidget, XmDIALOG_CANCEL_BUTTON); XtUnmanageChild(button); } if (!(buttons & MB_HELP)) { button = XmMessageBoxGetChild(dialogWidget, XmDIALOG_HELP_BUTTON); XtUnmanageChild(button); } if (buttons & MB_YES) { button = XtVaCreateManagedWidget("yes", xmPushButtonWidgetClass, dialogWidget, NULL); XtAddCallback(button, XmNactivateCallback, MBYes, this); } if (buttons & MB_NO) { button = XtVaCreateManagedWidget("no", xmPushButtonWidgetClass, dialogWidget, NULL); XtAddCallback(button, XmNactivateCallback, MBNo, this); } } sh_MessageBox::~sh_MessageBox() { void MBunmap(Widget w, XtPointer userData, XtPointer callbackData); if (dialogWidget) { XtRemoveCallback(dialogWidget, XmNunmapCallback, MBunmap, this); XtUnmanageChild(dialogWidget); } } void MBunmap(Widget, XtPointer mb, XtPointer) { sh_MessageBox *dialog = (sh_MessageBox *)mb; if (dialog->dialogWidget) { XtDestroyWidget(dialog->dialogWidget); dialog->dialogWidget = 0; if (dialog->autoDelete) delete dialog; else if (!dialog->dialogReply) dialog->dialogReply = IDCANCEL; } } void MBOk(Widget , XtPointer dialog, XtPointer ) { ((sh_MessageBox *)dialog)->Ok(); } void MBCancel(Widget , XtPointer dialog, XtPointer ) { ((sh_MessageBox *)dialog)->Cancel(); } void MBYes(Widget , XtPointer dialog, XtPointer ) { ((sh_MessageBox *)dialog)->Yes(); } void MBNo(Widget , XtPointer dialog, XtPointer ) { ((sh_MessageBox *)dialog)->No(); } void sh_MessageBox::Create() { XtManageChild(dialogWidget); XtPopup(XtParent(dialogWidget), XtGrabNone); } int sh_MessageBox::Execute() { Arg args[1]; XEvent event; dialogReply = 0; autoDelete = false; XtSetArg(args[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); XtSetValues(dialogWidget, args, 1); Create(); for (;;) { XtAppNextEvent(sh_MainWindow::GetMainWindow()->GetAppContext(), &event); XtDispatchEvent(&event); if (dialogReply) return dialogReply; } } void sh_MessageBox::Ok() { dialogReply = IDOK; XtUnmanageChild(dialogWidget); } void sh_MessageBox::Cancel() { dialogReply = IDCANCEL; XtUnmanageChild(dialogWidget); } void sh_MessageBox::Yes() { dialogReply = IDYES; XtUnmanageChild(dialogWidget); } void sh_MessageBox::No() { dialogReply = IDNO; XtUnmanageChild(dialogWidget); } /* -------------------------------------------------------------------------------------- sh_Control -------------------------------------------------------------------------------------- */ // a callback functions void sh_ControlEventCB(Widget, XtPointer control, XtPointer ) { ((sh_Control *)control)->ControlEvent(); } void sh_ControlTransferFromCB(Widget, XtPointer control, XtPointer ) { ((sh_Control *)control)->TransferFromControl(); } // member functions sh_Control::sh_Control(sh_CompositeControl *aparent, sh_EventHandler *event_handler) { m_event_handler = event_handler; parent = aparent; nextControl = NULL; valueChanged = false; widget = NULL; if (parent) parent->AddControl(this); } sh_Control::~sh_Control() { if (m_event_handler) { sh_Event ev("ControlClosed"); m_event_handler->ControlEvent(this, ev); } } void sh_Control::HideControl() { XtUnmanageChild(GetWidget()); } void sh_Control::ShowControl() { XtManageChild(GetWidget()); } void sh_Control::HasXPosition(int x) { XtVaSetValues(widget, XmNx, x, NULL); } void sh_Control::HasYPosition(int y) { XtVaSetValues(widget, XmNy, y, NULL); } void sh_Control::HasWidth(int width) { XtVaSetValues(widget, XmNwidth, width, NULL); } void sh_Control::HasHeight(int height) { XtVaSetValues(widget, XmNheight, height, NULL); } void sh_Control::IsAbove(sh_Control *c, int offset) { Arg args[3]; Widget w = c?c->GetWidget():NULL; if (c) XtSetArg(args[0], XmNbottomAttachment, XmATTACH_WIDGET); else XtSetArg(args[0], XmNbottomAttachment, XmATTACH_FORM); XtSetArg(args[1], XmNbottomWidget, w); XtSetArg(args[2], XmNbottomOffset, offset); XtSetValues(widget, args, 3); } void sh_Control::IsBelow(sh_Control *c, int offset) { Arg args[3]; Widget w = c?c->GetWidget():NULL; if (c) XtSetArg(args[0], XmNtopAttachment, XmATTACH_WIDGET); else XtSetArg(args[0], XmNtopAttachment, XmATTACH_FORM); XtSetArg(args[1], XmNtopWidget, w); XtSetArg(args[2], XmNtopOffset, offset); XtSetValues(widget, args, 3); } void sh_Control::IsLeftOf(sh_Control *c, int offset) { Arg args[3]; Widget w = c?c->GetWidget():NULL; if (c) XtSetArg(args[0], XmNrightAttachment, XmATTACH_WIDGET); else XtSetArg(args[0], XmNrightAttachment, XmATTACH_FORM); XtSetArg(args[1], XmNrightWidget, w); XtSetArg(args[2], XmNrightOffset, offset); XtSetValues(widget, args, 3); } void sh_Control::IsRightOf(sh_Control *c, int offset) { Arg args[3]; Widget w = c?c->GetWidget():NULL; if (c) XtSetArg(args[0], XmNleftAttachment, XmATTACH_WIDGET); else XtSetArg(args[0], XmNleftAttachment, XmATTACH_FORM); XtSetArg(args[1], XmNleftWidget, w); XtSetArg(args[2], XmNleftOffset, offset); XtSetValues(widget, args, 3); } void sh_Control::HasSameTopAs(sh_Control *c, int offset) { Arg args[3]; Widget w = c?c->GetWidget():NULL; if (c) XtSetArg(args[0], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); else XtSetArg(args[0], XmNtopAttachment, XmATTACH_OPPOSITE_FORM); XtSetArg(args[1], XmNtopWidget, w); XtSetArg(args[2], XmNtopOffset, offset); XtSetValues(widget, args, 3); } void sh_Control::HasSameBottomAs(sh_Control *c, int offset) { Arg args[3]; Widget w = c?c->GetWidget():NULL; if (c) XtSetArg(args[0], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); else XtSetArg(args[0], XmNbottomAttachment, XmATTACH_OPPOSITE_FORM); XtSetArg(args[1], XmNbottomWidget, w); XtSetArg(args[2], XmNbottomOffset, offset); XtSetValues(widget, args, 3); } void sh_Control::HasSameLeftAs(sh_Control *c, int offset) { Arg args[3]; Widget w = c?c->GetWidget():NULL; if (c) XtSetArg(args[0], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); else XtSetArg(args[0], XmNleftAttachment, XmATTACH_OPPOSITE_FORM); XtSetArg(args[1], XmNleftWidget, w); XtSetArg(args[2], XmNleftOffset, offset); XtSetValues(widget, args, 3); } void sh_Control::HasSameRightAs(sh_Control *c, int offset) { Arg args[3]; Widget w = c?c->GetWidget():NULL; if (c) XtSetArg(args[0], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); else XtSetArg(args[0], XmNrightAttachment, XmATTACH_OPPOSITE_FORM); XtSetArg(args[1], XmNrightWidget, w); XtSetArg(args[2], XmNrightOffset, offset); XtSetValues(widget, args, 3); } void sh_Control::HasTopPosition(int percent) { Arg args[2]; XtSetArg(args[0], XmNtopAttachment, XmATTACH_POSITION); XtSetArg(args[1], XmNtopPosition, percent); XtSetValues(widget, args, 2); } void sh_Control::HasBottomPosition(int percent) { Arg args[2]; XtSetArg(args[0], XmNbottomAttachment, XmATTACH_POSITION); XtSetArg(args[1], XmNbottomPosition, percent); XtSetValues(widget, args, 2); } void sh_Control::HasLeftPosition(int percent) { Arg args[2]; XtSetArg(args[0], XmNleftAttachment, XmATTACH_POSITION); XtSetArg(args[1], XmNleftPosition, percent); XtSetValues(widget, args, 2); } void sh_Control::HasRightPosition(int percent) { Arg args[2]; XtSetArg(args[0], XmNrightAttachment, XmATTACH_POSITION); XtSetArg(args[1], XmNrightPosition, percent); XtSetValues(widget, args, 2); } void sh_Control::ControlEvent(sh_Control *) { valueChanged = true; if (m_event_handler) { sh_Event ev("ValueChanged"); m_event_handler->ControlEvent(this, ev); } if (parent) parent->ControlEvent(this); } char *sh_Control::GetName() { return XtName(GetWidget()); } /* -------------------------------------------------------------------------------------- sh_CompositeControl -------------------------------------------------------------------------------------- */ sh_CompositeControl::sh_CompositeControl(sh_CompositeControl *aparent, sh_EventHandler *event_handler) : sh_Control(aparent, event_handler) { firstControl = lastControl = NULL; } sh_CompositeControl::~sh_CompositeControl() { sh_Control::~sh_Control(); sh_Control *c = firstControl; while (c) { sh_Control *d = c->nextControl; delete c; c = d; } } void sh_CompositeControl::AddControl(sh_Control *c) { if(!firstControl) firstControl = c; else lastControl->nextControl = c; lastControl = c; c->nextControl = NULL; c->parent = this; c->valueChanged = false; } void sh_CompositeControl::RemoveControl(sh_Control *c) { sh_CompositeControl *d = c->parent; if (d) { if (c == d->firstControl) { d->firstControl = d->firstControl->nextControl; if (d->lastControl == c) d->lastControl = 0; } else { sh_Control *prev = d->firstControl; while (prev && prev->nextControl != c) prev = prev->nextControl; if (prev) { prev->nextControl = c->nextControl; if (d->lastControl == c) d->lastControl = prev; } } } c->parent = 0; Widget w = c->GetWidget(); if (w) { XtDestroyWidget(w); delete c; } } void sh_CompositeControl::Ok() { if (parent) parent->Ok(); } void sh_CompositeControl::Cancel() { if (parent) parent->Cancel(); } void sh_CompositeControl::Yes() { if (parent) parent->Yes(); } void sh_CompositeControl::No() { if (parent) parent->No(); } void sh_CompositeControl::Apply() { if (parent) parent->Apply(); } void sh_CompositeControl::TransferToControl() { sh_Control *c = firstControl; while (c) { c->TransferToControl(); c->valueChanged = false; c = c->nextControl; } } void sh_CompositeControl::TransferFromControl() { sh_Event event("Apply"); sh_Control *c = firstControl; while (c) { if (c->valueChanged) { c->TransferFromControl(); c->valueChanged = false; if (c->m_event_handler) c->m_event_handler->ControlEvent(c, event); } c = c->nextControl; } if (!parent) if (m_event_handler) m_event_handler->ControlEvent(this, event); } void sh_CompositeControl::Start() { sh_Control *c = firstControl; while (c) { c->Start(); c = c->nextControl; } } /* -------------------------------------------------------------------------------------- sh_Form -------------------------------------------------------------------------------------- */ sh_Form::sh_Form(sh_CompositeControl *aparent, sh_EventHandler *event_handler) : sh_CompositeControl(aparent, event_handler) { if (parent) if (parent->GetWidget()) widget = XtVaCreateManagedWidget("sh_Form", xmFormWidgetClass, parent->GetWidget(), XmNfractionBase, 100, NULL); } /* -------------------------------------------------------------------------------------- sh_FramedControl for FramedControls, close sequence is: 1) unmap, either by calling XtUnmanageChild() (e.g. in 'ok' button) or by user closing on frame 2) sh_FramedControlUnmap call back is called (must add this as XmNunmapCallback) 2.1) request destroy widget 2.2) delete control objects 3) (any XtNdestroyCallback are called) 4) widgets are destroyed ..and this is why you can not delete controls directly! -------------------------------------------------------------------------------------- */ sh_FramedControl::sh_FramedControl(sh_EventHandler *event_handler) : sh_CompositeControl(NULL, event_handler) { autoDelete = true; } void sh_FramedControlUnmap(Widget , XtPointer control, XtPointer ) { sh_FramedControl *framedControl = (sh_FramedControl *)control; if (framedControl->widget) { XtDestroyWidget(framedControl->widget); framedControl->widget = 0; if (framedControl->autoDelete) { delete framedControl; } else if (!framedControl->dialogReply) framedControl->dialogReply = IDCANCEL; } } void sh_FramedControl::Create() { if (!widget) return; TransferToControl(); XtManageChild(widget); XtPopup(XtParent(widget), XtGrabNone); Start(); } int sh_FramedControl::Execute() { XtAppContext app = sh_MainWindow::GetMainWindow()->GetAppContext(); Arg args[1]; XEvent event; if (!widget) return 0; dialogReply = 0; autoDelete = false; XtSetArg(args[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); XtSetValues(widget, args, 1); Create(); for (;;) { XtAppNextEvent(app, &event); XtDispatchEvent(&event); if (dialogReply) return dialogReply; #if defined (CADSHELL) sh_CADshell::GetShell()->PerformModelChangeNotify(); #endif } } void sh_FramedControl::Ok() { Apply(); dialogReply = IDOK; if (widget) XtUnmanageChild(widget); } void sh_FramedControl::Cancel() { dialogReply = IDCANCEL; if (widget) XtUnmanageChild(widget); } void sh_FramedControl::Yes() { dialogReply = IDYES; if (widget) XtUnmanageChild(widget); } void sh_FramedControl::No() { dialogReply = IDNO; if (widget) XtUnmanageChild(widget); } void sh_FramedControl::Apply() { TransferFromControl(); if (m_event_handler) m_event_handler->Apply(); } /* -------------------------------------------------------------------------------------- sh_Dialog -------------------------------------------------------------------------------------- */ sh_Dialog::sh_Dialog(const char *name, sh_EventHandler *event_handler) : sh_FramedControl(event_handler) { Arg args[3]; XmString title = XmStringCreateSimple((char *)name); XtSetArg(args[0], XmNfractionBase, 100); XtSetArg(args[1], XmNautoUnmanage, false); XtSetArg(args[2], XmNdialogTitle, title); widget = XmCreateFormDialog(sh_MainWindow::GetMainWindow()->GetTopWidget(), (char *)name, args, 3); XtAddCallback(widget, XmNunmapCallback, sh_FramedControlUnmap, this); XmStringFree(title); } /* -------------------------------------------------------------------------------------- sh_FileDialog -------------------------------------------------------------------------------------- */ sh_FileDialog::sh_FileDialog(const char *name, char **apfilename, char **apdir, char **apmask, sh_EventHandler *event_handler) : sh_FramedControl(event_handler) { void sh_FileDialogOkCB(Widget w, XtPointer client_data, XtPointer cbs); void sh_FileDialogCancelCB(Widget w, XtPointer client_data, XtPointer cbs); Widget remove; XmString title, dir, mask; Arg args[5]; int n = 0; pfilename = apfilename; pdir = apdir; pmask = apmask; title = XmStringCreateSimple((char *)name); XtSetArg(args[n], XmNdialogTitle, title); n++; if (pdir) { dir = XmStringCreateSimple(*pdir); XtSetArg(args[n], XmNdirectory, dir); n++; } if (pmask) { mask = XmStringCreateSimple(*pmask); XtSetArg(args[n], XmNpattern, mask); n++; } XtSetArg(args[n], XmNtextColumns, 40); n++; widget = XmCreateFileSelectionDialog(sh_MainWindow::GetMainWindow()->GetTopWidget(), (char*)"select", args, n); XtAddCallback(widget, XmNokCallback, sh_FileDialogOkCB, this); XtAddCallback(widget, XmNcancelCallback, sh_FileDialogCancelCB, this); XtAddCallback(widget, XmNunmapCallback, sh_FramedControlUnmap, this); remove = XmSelectionBoxGetChild(widget, XmDIALOG_HELP_BUTTON); XtUnmanageChild(remove); XmStringFree(title); if (pmask) XmStringFree(mask); if (pdir) XmStringFree(dir); } void sh_FileDialog::SetSelectionLabel(const char *str) { XmString label = XmStringCreateSimple((char *)str); XtVaSetValues(widget, XmNselectionLabelString, label, NULL); XmStringFree(label); } void sh_FileDialog::TransferFromControl() { XmString filename, dir, mask; char *filenameStr, *dirStr, *maskStr; XtVaGetValues(widget, XmNdirSpec, &filename, XmNpattern, &mask, XmNdirectory, &dir, NULL); XmStringGetLtoR(filename, XmSTRING_DEFAULT_CHARSET, &filenameStr); XmStringGetLtoR(mask, XmSTRING_DEFAULT_CHARSET, &maskStr); XmStringGetLtoR(dir, XmSTRING_DEFAULT_CHARSET, &dirStr); XmStringFree(filename); XmStringFree(mask); XmStringFree(dir); if (filenameStr) { if (pfilename) { if (*pfilename) free (*pfilename); *pfilename = filenameStr; } else free(filenameStr); } if (maskStr) { if (pmask) { if (*pmask) free (*pmask); *pmask = maskStr; } else free(maskStr); } if (dirStr) { if (pdir) { if (*pdir) free (*pdir); *pdir = dirStr; } else free(dirStr); } sh_CompositeControl::TransferFromControl(); } void sh_FileDialogOkCB(Widget, XtPointer fileDialog, XtPointer) { if (fileDialog) ((sh_FileDialog*)fileDialog)->Ok(); } void sh_FileDialogCancelCB(Widget, XtPointer fileDialog, XtPointer) { if (fileDialog) ((sh_FileDialog*)fileDialog)->Cancel(); } /* -------------------------------------------------------------------------------------- Button Controls -------------------------------------------------------------------------------------- */ sh_Button::sh_Button(sh_CompositeControl *aparent, const char *label, sh_EventHandler *event_handler, bool enabled, char key) : sh_Control(aparent, event_handler) { if (aparent) { widget = XtVaCreateManagedWidget(label, xmPushButtonWidgetClass, aparent->GetWidget(), XmNsensitive, enabled, NULL); if (key) XtVaSetValues(widget, XmNmnemonic, key, NULL); XtAddCallback(widget, XmNactivateCallback, sh_ControlEventCB, this); } } bool sh_Button::SetPixmap(const char *pixmapFileName) { Pixel fg, bg; Pixmap pixmap; XtVaGetValues(parent->GetWidget(), XmNforeground, &fg, XmNbackground, &bg, NULL); pixmap = XmGetPixmap( XtScreen(parent->GetWidget()), (char *)pixmapFileName, fg, bg); if (pixmap == XmUNSPECIFIED_PIXMAP) return false; XtVaSetValues( widget, XmNlabelType, XmPIXMAP, XmNlabelPixmap, pixmap, NULL); return true; } bool sh_Button::SetText(const char *buttonText) { XmString string = XmStringCreateSimple((char *)buttonText); XtVaSetValues( widget, XmNlabelString, string, NULL); XmStringFree(string); return true; } void sh_Button::ControlEvent(sh_Control *) { if (m_event_handler) { sh_Event ev("ButtonPressed"); m_event_handler->ControlEvent(this, ev); } // sh_Control::ControlEvent(); // valueChanged = true; if (parent) parent->ControlEvent(this); } sh_OnOffButton::sh_OnOffButton(sh_CompositeControl *aparent, const char *label, sh_EventHandler *event_handler, bool enabled, char key) : sh_Button(aparent, event_handler) { widget = XtVaCreateManagedWidget(label, xmDrawnButtonWidgetClass, aparent->GetWidget(), XmNsensitive, enabled, XmNshadowThickness, 2, // XmNindicatorOn, false, // XmNfillOnSelect, true, // XmNbackground, 1, // XmNpushButtonEnabled, true, XmNshadowType, XmSHADOW_OUT, NULL); if (key) XtVaSetValues(widget, XmNmnemonic, key, NULL); XtAddCallback(widget, XmNactivateCallback, sh_ControlEventCB, this); } void sh_OkButton::ControlEvent(sh_Control *) { parent->Ok(); } void sh_CancelButton::ControlEvent(sh_Control *) { parent->Cancel(); } void sh_ApplyButton::ControlEvent(sh_Control *) { parent->Apply(); } sh_OkApplyCancel::sh_OkApplyCancel(sh_CompositeControl *aparent, sh_EventHandler *event_handler) : sh_Form(aparent, event_handler) { sh_Control *partition, *ok, *apply, *cancel; partition = new sh_Partition(this); ok = new sh_OkButton(this); apply = new sh_ApplyButton(this); cancel = new sh_CancelButton(this); partition->IsBelow(NULL, 0); ok->IsBelow(partition); apply->IsBelow(partition); cancel->IsBelow(partition); ok->IsAbove(NULL); ok->IsRightOf(NULL); apply->IsRightOf(ok); cancel->IsRightOf(apply); } sh_OkCancel::sh_OkCancel(sh_CompositeControl *aparent, sh_EventHandler *event_handler) : sh_Form(aparent, event_handler) { sh_Control *partition, *ok, *cancel; partition = new sh_Partition(this); ok = new sh_OkButton(this); cancel = new sh_CancelButton(this); partition->IsBelow(NULL, 0); ok->IsBelow(partition); cancel->IsBelow(partition); ok->IsAbove(NULL); ok->IsRightOf(NULL); cancel->IsRightOf(ok); } sh_CheckBox::sh_CheckBox(sh_CompositeControl *aparent, const char *name, bool *b, sh_EventHandler *event_handler, bool enabled) : sh_Control(aparent, event_handler) { p = b; widget = XtVaCreateManagedWidget(name, xmToggleButtonWidgetClass, parent->GetWidget(), XmNsensitive, enabled, NULL); XtAddCallback(widget, XmNvalueChangedCallback, sh_ControlEventCB, this); } void sh_CheckBox::TransferToControl() { XmToggleButtonSetState(widget, *p, false); } void sh_CheckBox::TransferFromControl() { *p = XmToggleButtonGetState(widget); } void sh_CheckBox::ControlEvent(sh_Control *) { /* if (m_event_handler) { sh_Event ev("CheckBoxToggled"); m_event_handler->ControlEvent(this, ev); } */ sh_Control::ControlEvent(); } /* -------------------------------------------------------------------------------------- Text and Labels -------------------------------------------------------------------------------------- */ sh_Label::sh_Label(sh_CompositeControl *aparent, const char *s) : sh_Control(aparent) { XmString string = XmStringCreateSimple((char *)s); widget = XtVaCreateManagedWidget("sh_Label", xmLabelWidgetClass, parent->GetWidget(), XmNlabelString, string, NULL); XmStringFree(string); } sh_Bitmap::sh_Bitmap(const char *bitmapFile, int ax_hotspot, int ay_hotspot) { _x_hotspot = ax_hotspot; _y_hotspot = ay_hotspot; char s[150]; #if defined (CADSHELL) sprintf(s, "%s/%s", sh_CADshell::GetShell()->GetResourceDir(), bitmapFile); #else sprintf(s, "./%s", bitmapFile); #endif parent = sh_MainWindow::GetMainWindow(); if (!parent) { cout << "Programmer error: instantiating sh_Bitmap before main window is created.\n" << flush; return; } Pixel fg, bg; XtVaGetValues(parent->GetWidget(), XmNforeground, &fg, XmNbackground, &bg, NULL); bitmap = XmGetPixmap( XtScreen(parent->GetWidget()), (char *)bitmapFile, fg, bg); if (bitmap == XmUNSPECIFIED_PIXMAP) bitmap = XmGetPixmap( XtScreen(parent->GetWidget()), s, fg, bg); if (bitmap == XmUNSPECIFIED_PIXMAP) { bitmap = 0; cout << "Invalid bitmap file: " << bitmapFile << " or " << s << endl << flush; } if (bitmap) { Window win; int x, y; unsigned int border, depth; XGetGeometry(XtDisplay(parent->GetWidget()), bitmap, &win, &x, &y, &_width, &_height, &border, &depth); _x_hotspot += _width/2; _y_hotspot += _height/2; } } sh_Bitmap::~sh_Bitmap() { if (parent && bitmap) XmDestroyPixmap(XtScreen(parent->GetWidget()), bitmap); } sh_LabeledControls::sh_LabeledControls(sh_CompositeControl *aparent, const char *label, sh_EventHandler *event_handler) : sh_Form(aparent, event_handler) { sh_Control *c = new sh_Label(this, label); c->IsBelow(NULL, 0); c->IsRightOf(NULL, 0); } void sh_LabeledControls::PositionControls() { if (!firstControl) return; sh_Control *c, *last = firstControl; c = last->GetNextControl(); while(c) { c->IsRightOf(firstControl); if (last != firstControl) c->IsBelow(last, 5); // else // c->IsBelow(NULL); last = c; c = c->GetNextControl(); } } sh_Partition::sh_Partition(sh_CompositeControl *aparent, bool fullWidth) : sh_Control(aparent) { widget = XtVaCreateManagedWidget("partition", xmSeparatorWidgetClass, parent->GetWidget(), NULL); if (fullWidth) XtVaSetValues(widget, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL); } sh_TextInput::sh_TextInput(sh_CompositeControl *aparent, char *s, int amaxChars, bool SingleLine, bool ReadOnly, sh_EventHandler *event_handler) : sh_Control(aparent, event_handler) { p = s; maxChars = amaxChars; widget = XtVaCreateManagedWidget("Text", xmTextWidgetClass, parent->GetWidget(), XmNeditable, true, XmNeditMode, XmMULTI_LINE_EDIT, NULL); if (ReadOnly) XtVaSetValues(widget, XmNeditable, false, XmNcursorPositionVisible, false, NULL); if (SingleLine) XtVaSetValues(widget, XmNeditMode, XmSINGLE_LINE_EDIT, NULL); XtAddCallback(widget, XmNvalueChangedCallback, sh_ControlEventCB, this); } void sh_TextInput::SetText(const char *s) { XmTextSetString(widget, (char *)s); } void sh_TextInput::SetNumRows(int num_rows) { XtVaSetValues(widget, XmNrows, num_rows, NULL); } void sh_TextInput::SetNumColumns(int num_columns) { XtVaSetValues(widget, XmNcolumns, num_columns, NULL); } void sh_TextInput::TransferToControl() { XmTextSetString(widget, p); } void sh_TextInput::TransferFromControl() { char *s; s = XmTextGetString(widget); strncpy(p, s, maxChars); XtFree(s); } sh_TextInput_DynAlloc::sh_TextInput_DynAlloc(sh_CompositeControl *aparent, char **s, bool SingleLine, bool ReadOnly, sh_EventHandler *event_handler) : sh_Control(aparent, event_handler) { p = s; if (!s) printf("Programmer: must give valid pointer to a 'char *' in sh_TextInput_DynAlloc constructor"); widget = XtVaCreateManagedWidget("Text", xmTextWidgetClass, parent->GetWidget(), XmNeditable, true, XmNeditMode, XmMULTI_LINE_EDIT, NULL); if (ReadOnly) XtVaSetValues(widget, XmNcursorPositionVisible, false, NULL); // setting XmNeditable to false causes a core dump when the window closes, for some reason else XtAddCallback(widget, XmNvalueChangedCallback, sh_ControlEventCB, this); if (SingleLine) XtVaSetValues(widget, XmNeditMode, XmSINGLE_LINE_EDIT, NULL); } void sh_TextInput_DynAlloc::SetText(const char *s) { if (s) XmTextSetString(widget, (char *)s); else XmTextSetString(widget, (char *)""); } void sh_TextInput_DynAlloc::SetNumRows(int num_rows) { XtVaSetValues(widget, XmNrows, num_rows, NULL); } void sh_TextInput_DynAlloc::SetNumColumns(int num_columns) { XtVaSetValues(widget, XmNcolumns, num_columns, NULL); } void sh_TextInput_DynAlloc::TransferToControl() { if (!p) return; if (*p) XmTextSetString(widget, *p); else XmTextSetString(widget, (char *)""); } void sh_TextInput_DynAlloc::TransferFromControl() { if (!p) return; if (*p) free (*p); *p = XmTextGetString(widget); if (**p == 0) { XtFree(*p); *p = 0; } } sh_TextListInput::sh_TextListInput(sh_CompositeControl *aparent, int *apos, char **textlist, int anumLines, sh_EventHandler *event_handler) : sh_Control(aparent, event_handler) { Create(aparent, apos, 0, textlist, 0, anumLines); } sh_TextListInput::sh_TextListInput(sh_CompositeControl *aparent, void **apointer_pos, char **atextlist, void **apointerlist, int anumLines, sh_EventHandler *event_handler) : sh_Control(aparent, event_handler) { Create(parent, 0, apointer_pos, atextlist, apointerlist, anumLines); } sh_TextListInput::~sh_TextListInput() { sh_Control::~sh_Control(); if (pointerlist) free (pointerlist); } void sh_TextListInput::Create(sh_CompositeControl *aparent, int *apos, void **apointer_pos, char **textlist, void **aPointerList, int aNumLines) { XmStringTable l; int i; pos = apos; pointer_pos = apointer_pos; numLines = aNumLines; selectedPos = -1; selectedPointer = 0; pointerlist = 0; if (numLines) { l = (XmStringTable) XtMalloc(numLines * sizeof(XmString *)); for (i = 0; i < numLines; i++) l[i] = XmStringCreateSimple(textlist[i]); if (pointer_pos || aPointerList) { pointerlist = (void **)malloc(numLines * sizeof(void *)); for (i = 0; i < numLines; i++) if (aPointerList) pointerlist[i] = aPointerList[i]; else pointerlist[i] = 0; } } list = XmCreateScrolledList(aparent->GetWidget(), (char*)"TextList", NULL, 0); XtVaSetValues(list, XmNvisibleItemCount, 7, NULL); XtAddCallback(list, XmNbrowseSelectionCallback, sh_TextListInputlistSelectCB, this); XtAddCallback(list, XmNbrowseSelectionCallback, sh_ControlEventCB, this); XtManageChild(list); if (numLines) { XtVaSetValues(list, XmNitemCount, numLines, XmNitems, l, NULL); for (i = 0; i < numLines; i++) XmStringFree(l[i]); XtFree((char*)l); } widget = XtParent(list); } void sh_TextListInputlistSelectCB(Widget, XtPointer textListControl, XtPointer list_cbs) { sh_TextListInput *tl = (sh_TextListInput*)textListControl; tl->selectedPos = ((XmListCallbackStruct *)list_cbs)->item_position - 1; if (tl->pointerlist) tl->selectedPointer = tl->pointerlist[tl->selectedPos]; } void sh_TextListInput::AddListItem(const char *s, int apos) { AddListItem(s, 0, apos); } void sh_TextListInput::ReplaceListItem(const char *s, int apos) { ReplaceListItem(s, 0, apos); } void sh_TextListInput::AddListItem(const char *s, void *pointer, int apos) { numLines++; XmString ss = XmStringCreateSimple((char *)s); XmListAddItem(list, ss, apos==-1? 0: apos+1); XmStringFree(ss); if (pointer_pos || pointerlist || pointer) { pointerlist = (void **)realloc(pointerlist, numLines*sizeof(void*)); if (apos != -1) for (int i=numLines-2; i>=apos; i--) pointerlist[i+1] = pointerlist[i]; pointerlist[apos==-1?numLines-1:apos] = pointer; } } void sh_TextListInput::ReplaceListItem(const char *s, void *pointer, int apos) { if (apos >= numLines) return; XmString ss = XmStringCreateSimple((char *)s); XmListReplaceItemsPos(list, &ss, 1, apos+1); XmStringFree(ss); if (pointerlist) pointerlist[apos] = pointer; if (selectedPos != -1) XmListSelectPos(list, selectedPos+1, false); } void sh_TextListInput::RemoveListItem(int apos) { numLines--; XmListDeletePos(list, apos==-1?0:apos+1); if (pointerlist) { if (apos != -1) for (int i=apos; iGetWidget(), NULL); // option_menu = XmVaCreateSimpleOptionMenu(widget, "option_menu", label, title?title[0]:0, 0, 0, NULL); option_menu = widget = XmVaCreateSimpleOptionMenu(aparent->GetWidget(), (char*)"option_menu", label, title?title[0]:0, 0, 0, NULL); // XtManageChild(option_menu); XtManageChild(widget); XmStringFree(label); if (aOptionList) for (int i=0; i < aNumOptions; i++) AddOption(aOptionList[i], aOptionPointerList?aOptionPointerList[i]:0); } void sh_OptionSelectCB(Widget button, XtPointer optionSelectControl, XtPointer ) { sh_OptionSelect *os = (sh_OptionSelect*)optionSelectControl; for (int i = 0; inumOptions; i++) if (os->buttonList[i] == button) { os->selectedOptionNo = i; if (os->optionPointerList) os->selectedOptionPointer = os->optionPointerList[i]; } if (os->m_event_handler) { sh_Event ev("OptionSelected"); os->m_event_handler->ControlEvent(os, ev); } } void sh_OptionSelect::AddOption(const char *s) { AddOption(s, 0); } void sh_OptionSelect::AddOption(const char *s, void *pointer) { Widget pulldown; if (!s) return; numOptions++; XtVaGetValues(option_menu, XmNsubMenuId, &pulldown, NULL); Widget button = XtVaCreateManagedWidget(s, xmPushButtonWidgetClass, pulldown, NULL); XtAddCallback(button, XmNactivateCallback, sh_ControlEventCB, this); XtAddCallback(button, XmNactivateCallback, sh_OptionSelectCB, this); optionPointerList = (void **)realloc(optionPointerList, numOptions*sizeof(void*)); buttonList = (Widget *)realloc(buttonList, numOptions*sizeof(Widget)); optionPointerList[numOptions-1] = pointer; buttonList[numOptions-1] = button; } void sh_OptionSelect::TransferToControl() { if (!numOptions) return; selectedOptionNo = 0; selectedOptionPointer = optionPointerList[0]; if (optionNo) { if (*optionNo < numOptions) { selectedOptionNo = *optionNo; selectedOptionPointer = optionPointerList[*optionNo]; } else { selectedOptionNo = 0; selectedOptionPointer = 0; } } else if (optionPointer && *optionPointer) { selectedOptionNo = -1; for (int i=0; iGetWidget(), XmNwidth, 50, XmNheight, 50, NULL); } /* -------------------------------------------------------------------------------------- Value input -------------------------------------------------------------------------------------- */ sh_IntInput::sh_IntInput(sh_CompositeControl *aparent, int *i, sh_EventHandler *event_handler) : sh_Control(aparent, event_handler) { p = i; widget = XtVaCreateManagedWidget("IntInput", xmTextFieldWidgetClass, parent->GetWidget(), XmNcolumns, 6, XmNeditable, true, NULL); XtAddCallback(widget, XmNvalueChangedCallback, sh_ControlEventCB, this); } void sh_IntInput::TransferToControl() { char s[20]; sprintf(s, "%i ", *p); XmTextFieldSetString(widget, s); } void sh_IntInput::TransferFromControl() { char *s; s = XmTextFieldGetString(widget); if (!sscanf(s, "%i", p)) { char ss[50]; sprintf(ss, "Bad input: '%.20s'. Default used.", s); sh_MessageBox::Message(ss); } XtFree(s); } sh_DoubleInput::sh_DoubleInput(sh_CompositeControl *aparent, double *f, sh_EventHandler *event_handler) : sh_Control(aparent, event_handler) { p = f; widget = XtVaCreateManagedWidget("DoubleInput", xmTextFieldWidgetClass, parent->GetWidget(), XmNcolumns, 12, XmNeditable, true, NULL); XtAddCallback(widget, XmNvalueChangedCallback, sh_ControlEventCB, this); } void sh_DoubleInput::TransferToControl() { char s[20]; sprintf(s, "%8.6lG ", *p); XmTextFieldSetString(widget, s); } void sh_DoubleInput::TransferFromControl() { char *s; s = XmTextFieldGetString(widget); if (!sscanf(s, "%lf", p)) { char ss[50]; sprintf(ss, "Bad input: '%.20s'. Default used.", s); sh_MessageBox::Message(ss); } XtFree(s); } sh_DoubleInputWithUnits::sh_DoubleInputWithUnits(sh_CompositeControl *aparent, double *f, const char *aunits, bool ametric, sh_EventHandler *event_handler) : sh_Control(aparent, event_handler) { p = f; if (aunits) strncpy(units, aunits, UNITSSTRLEN); else units[0] = 0; metric = ametric; widget = XtVaCreateManagedWidget("FloatInput", xmTextFieldWidgetClass, parent->GetWidget(), XmNcolumns, 12, XmNeditable, true, NULL); XtAddCallback(widget, XmNvalueChangedCallback, sh_ControlEventCB, this); } void sh_DoubleInputWithUnits::TransferToControl() { char s[80], u[UNITSSTRLEN]; double af; af = *p; if (units[0]) { strcpy(u, units); if (metric) KMS2(&af, u, TRUE); else Imp2(&af, u, TRUE); sprintf(s, "%9.5G %s ", af, u); } else sprintf(s, "%9.5G ", af); XmTextFieldSetString(widget, s); } void sh_DoubleInputWithUnits::TransferFromControl() { char s[80], *xs, u[UNITSSTRLEN], u2[UNITSSTRLEN]; double af; strcpy(u,""); af = 0.; xs = XmTextFieldGetString(widget); if (units[0]) { sscanf(xs,"%lf%s", &af, u); strcpy(u2, u); KMS2(&af, u2); if (stricmp(u2,units)) { sprintf(s, "'%s' does not convert to '%s'.", u, units); sh_MessageBox *m = new sh_MessageBox(s); m->Create(); } else *p = af; } else if (!sscanf(xs,"%lf", p)) { char ss[50]; sprintf(ss, "Bad input: '%.20s'. Default used.", xs); sh_MessageBox::Message(ss); } XtFree(xs); } sh_ExpressionInput::sh_ExpressionInput(sh_CompositeControl *aparent, char **aexpression, const char *aunits, bool ametric, sh_EventHandler *event_handler) : sh_Control(aparent, event_handler) { expression = aexpression; if (aunits) strncpy(units, aunits, UNITSSTRLEN); else units[0] = 0; metric = ametric; widget = XtVaCreateManagedWidget("ExpressionInput", xmTextFieldWidgetClass, parent->GetWidget(), XmNcolumns, 15, XmNeditable, true, NULL); XtAddCallback(widget, XmNvalueChangedCallback, sh_ControlEventCB, this); } void sh_ExpressionInput::TransferToControl() { char s[180], u[UNITSSTRLEN]; double af; int num; if (!expression || !(*expression)) return; num = sscanf(*expression, "%lf%s", &af, s); if (num==1) { if (units && units[0]) { strcpy(u, units); if (metric) KMS2(&af, u, TRUE); else Imp2(&af, u, TRUE); sprintf(s, "%9.5G (%s) ", af, u); } else sprintf(s, "%9.5G ", af); } else { if (units && units[0]) sprintf(s, "%s (%s)", *expression, units); else sprintf(s, "%s", *expression); } XmTextFieldSetString(widget, s); } void sh_ExpressionInput::TransferFromControl() { char s[180], *xs, u[UNITSSTRLEN], u2[UNITSSTRLEN]; double af; int num; if (!expression) return; if (*expression) { free (*expression); *expression = 0; } strcpy(u,""); af = 0.; xs = XmTextFieldGetString(widget); if (units && units[0]) { // scan for number & units num = sscanf(xs,"%lf%s", &af, u); if (num == 2 && u[0] == '(') { strcpy(u2, u+1); if (u2[strlen(u2)-1] == ')') u2[strlen(u2)-1] = 0; // get rid of closing bracket KMS2(&af, u2); if (stricmp(u2,units)) { sprintf(s, "'%s' does not convert to '%s'.", u, units); sh_MessageBox *m = new sh_MessageBox(s); m->Create(); } else { sprintf(s, "%lG", af); *expression = strdup(s); } } else { bool bad = false; char *xs2 = strdup(xs); char *u3 = strrchr(xs2, ')'); if (!u3) bad = true; if (!bad) { *u3 = 0; u3 = strrchr(xs2, '('); if (!u3) bad = true; } if (!bad) { *u3 = 0; u3++; if (!stricmp(u3, units)) *expression = strdup(xs2); else bad = true; } if (bad) { sh_MessageBox *m = new sh_MessageBox("Can not change units of expression"); m->Create(); } free (xs2); } } else { *expression = strdup(xs); if (**expression == 0) { free (*expression); *expression = 0; } } XtFree(xs); } sh_Slider::sh_Slider(sh_CompositeControl *aparent, double *f, bool vert, bool autoUpdate, sh_EventHandler *event_handler) : sh_Control(aparent, event_handler) { Arg args[5]; XtSetArg(args[0], XmNdecimalPoints, 2); XtSetArg(args[1], XmNmaximum, 100); XtSetArg(args[2], XmNminimum, 0); if (vert) XtSetArg(args[3], XmNorientation, XmVERTICAL); else XtSetArg(args[3], XmNorientation, XmHORIZONTAL); XtSetArg(args[4], XmNhighlightOnEnter, true); p = f; widget = XtCreateManagedWidget("Slider", xmScaleWidgetClass, parent->GetWidget(), args, 5); if (autoUpdate) XtAddCallback(widget, XmNdragCallback, sh_ControlTransferFromCB, this); XtAddCallback(widget, XmNdragCallback, sh_ControlEventCB, this); if (autoUpdate) XtAddCallback(widget, XmNvalueChangedCallback, sh_ControlTransferFromCB, this); XtAddCallback(widget, XmNvalueChangedCallback, sh_ControlEventCB, this); } void sh_Slider::TransferToControl() { int v; v = (int)((*p)*100.); XmScaleSetValue(widget, v); } void sh_Slider::TransferFromControl() { int v; XmScaleGetValue(widget, &v); *p = (double)v*.01; } void sh_Slider::ControlEvent(sh_Control *) { if (m_event_handler) { sh_Event ev("SliderSlid"); m_event_handler->ControlEvent(this, ev); } sh_Control::ControlEvent(); } sh_Scrollbar::sh_Scrollbar(sh_CompositeControl *aparent, double *f, bool vert, bool autoUpdate, sh_EventHandler *event_handler) : sh_Control(aparent, event_handler) { Arg args[5]; XtSetArg(args[0], XmNpageIncrement, 10); XtSetArg(args[1], XmNmaximum, 100); XtSetArg(args[2], XmNminimum, 0); if (vert) XtSetArg(args[3], XmNorientation, XmVERTICAL); else XtSetArg(args[3], XmNorientation, XmHORIZONTAL); XtSetArg(args[4], XmNhighlightOnEnter, true); p = f; widget = XtCreateManagedWidget("Scrollbar", xmScrollBarWidgetClass, parent->GetWidget(), args, 5); if (autoUpdate) XtAddCallback(widget, XmNdragCallback, sh_ControlTransferFromCB, this); XtAddCallback(widget, XmNdragCallback, sh_ControlEventCB, this); if (autoUpdate) XtAddCallback(widget, XmNvalueChangedCallback, sh_ControlTransferFromCB, this); XtAddCallback(widget, XmNvalueChangedCallback, sh_ControlEventCB, this); } void sh_Scrollbar::TransferToControl() { int v; v = (int)((*p * (1.-0.15))*100.); XmScrollBarSetValues(widget, v, 15, 1, 10, false); } void sh_Scrollbar::TransferFromControl() { int v, v1, v2, v3; XmScrollBarGetValues(widget, &v, &v1, &v2, &v3); *p = (double)v/(100-v1); } void sh_Scrollbar::ControlEvent(sh_Control *) { if (m_event_handler) { sh_Event ev("ScrollbarSlid"); m_event_handler->ControlEvent(this, ev); } sh_Control::ControlEvent(); } sh_Vec3dInput::sh_Vec3dInput(sh_CompositeControl *aparent, double *d, sh_EventHandler *event_handler) : sh_Form(aparent, event_handler) { sh_LabeledControls *x, *y, *z; x = new sh_LabeledControls(this, "x "); new sh_DoubleInput(x, &(d[0])); x->PositionControls(); y = new sh_LabeledControls(this, "y "); new sh_DoubleInput(y, &(d[1])); y->PositionControls(); z = new sh_LabeledControls(this, "z "); new sh_DoubleInput(z, &(d[2])); z->PositionControls(); x->IsRightOf(NULL); y->IsRightOf(NULL); z->IsRightOf(NULL); x->IsBelow(NULL,0); y->IsBelow(x, 1); z->IsBelow(y, 1); z->IsAbove(NULL,0); } /* -------------------------------------------------------------------------------------- unit conversion functions -------------------------------------------------------------------------------------- */ void Weed(char *unit) { int i, j; for (i=1; iCreate(); return FALSE; } if (Common) CommonMetric(val, unit); return TRUE; } void CommonMetric(double *val, char *unit) { int i; struct TCommon { const char* OrigUnits; double Min, Max, Multiplier; const char* NewUnits; }; // --------------------------------------------------------------------------------------- static const TCommon Common[] = { { "M", 1.E-5, .1, 1000., "mm" }, { "RAD", 0., 1.E+20, 57.29577951, "deg" }, // 180/pi { "RAD/S", 0., 1.E+20, .1591549431, "Hz" }, // 1/(2*pi) { "RATIO", 0., 1.E+20, 100., "%%" }, { "S", 86400., 31556736., 1.157407E-5, "days" }, { "S", 31556736., 1.E+20, 3.168896E-8, "years" }, { "W", 1000., 1.E+6, .001, "kW" }, { "W", 1.E+6, 1.E+9, 1.E-6, "MW" }, { "V", 1000., 1.E+6, .001, "kV" }, { "Last", 0.0, 0.0, 0.0, "" }, }; for (i = 0; strcmp(Common[i].OrigUnits, "Last"); i++) if (!stricmp(unit, Common[i].OrigUnits)) if (fabs(*val) >= Common[i].Min && fabs(*val) <= Common[i].Max) { *val *= Common[i].Multiplier; sprintf(unit,Common[i].NewUnits); return; } if (!stricmp(unit, "K")) { *val -= 273.15; sprintf(unit, "C"); return; } } // this function contains a function to convert // values to the imperial unit convention // // returns FALSE if no or unrecognizable // units are given. // // angle unit is radians // distance feet // mass slug // time second // force pound force // temperature degrees Rankine bool Imp(double *val, char *unit) { int i; static const char *StaySame[] = { "FT", "S", "SEC", "SLUG", "RAD", "FT/S", "RAD/S", "RAD/SEC", "FT/SEC", "FT/SEC^2", "FT/S^2", "SLUG/FT^3", "LB/FT^2", "LBF/FT^2", "LBF", "SLUG-FT^2", "SLUG FT^2", "LBF-S/FT^2", "RATIO", "LBF/(FT/S)", "LBF/FT", "NON-DIM", "Last" }; struct TChange { const char* OrigUnits; double Multiplier; const char* NewUnits; }; // ------------------------------------------------------------------------------ static const TChange Change[] = { { "RPM", .1047197551, "rad/s" }, // pi/30 { "HZ", 6.283185307, "rad/s" }, // 2*pi { "IN", .0833333333, "ft" }, { "M", 3.280839895, "ft" }, { "KG-M^2", .7375621493, "slug-ft^2" }, { "KG", .0685217659, "slug" }, { "N", .2248089431, "lbf" }, { "PA", .0208854342, "lbf/ft^2" }, { "KG/M^3", .0019403203, "slug/ft^3" }, { "DEG", .0174532925, "rad" }, // pi/180 { "DEGREES", .0174532925, "rad" }, // pi/180 { "N/M", .0685217659, "lbf/ft" }, { "N/(M/S)", .0685217659, "lbf/(ft/s)" }, { "KG-M", 7.233013851, "lb-ft" }, { "N-S/M^2", .0208854342, "lbf-s/ft^2" }, { "N-M", .7375621493, "lbf-ft" }, { "Last", 0.0, "" }, }; if (!strlen(unit)) return FALSE; Weed(unit); for (i = 0; strcmp(StaySame[i], "Last"); i++) if (!stricmp(unit, StaySame[i])) return TRUE; for (i = 0; strcmp(Change[i].OrigUnits, "Last"); i++) if (!stricmp(unit, Change[i].OrigUnits)) { *val *= Change[i].Multiplier; sprintf(unit,Change[i].NewUnits); return TRUE; } return FALSE; } bool Imp2(double *val, char *unit, bool Common) { char s[40]; if (unit[0] == '\n') return TRUE; if (!Imp(val, unit)) { if (!strlen(unit)) return TRUE; sprintf(s, "The units '%s' are not understood.", unit); sh_MessageBox *m = new sh_MessageBox(s, " ", MB_OK | MB_ICONEXCLAMATION); m->Create(); return FALSE; } if (Common) CommonImp(val, unit); return TRUE; } void CommonImp(double *val, char *unit) { int i; struct TCommon { const char* OrigUnits; double Min, Max, Multiplier; const char* NewUnits; }; // --------------------------------------------------------------------------------------- static const TCommon Common[] = { { "FT", 0., 8., 12., "in" }, { "RAD", 0., 1.E+20, 57.29577951, "deg" }, // 180/pi { "RAD/S", 0., 1.E+20, 9.549296586, "RPM" }, // 30/pi { "RATIO", 0., 1.E+20, 100., "%%" }, { "S", 86400., 31556736., 1.157407E-5, "days" }, { "S", 31556736., 1.E+20, 3.168896E-8, "years" }, { "Last", 0.0, 0.0, 0.0, "" }, }; for (i = 0; strcmp(Common[i].OrigUnits, "Last"); i++) if (!stricmp(unit, Common[i].OrigUnits)) if (fabs(*val) >= Common[i].Min && fabs(*val) <= Common[i].Max) { *val *= Common[i].Multiplier; sprintf(unit,Common[i].NewUnits); return; } } /* -------------------------------------------------------------------------------------- some string functions linecpy() copies up to end of line (when \n or \r is reached). linencpy() is same as linecpy() but only copies up to maxlen. stricmp() should be in string.h but isn't. (Compares without case sensitivity) -------------------------------------------------------------------------------------- */ char *linecpy(char *dest, const char *src) { int i = 0; while (src[i] && src[i]!=10 && src[i]!=13) { dest[i] = src[i]; i++; } dest[i] = 0; return dest; } char *linencpy(char *dest, const char *src, size_t maxlen) { int i = 0; while (src[i] && src[i]!=10 && src[i]!=13 && i