//----------------------------------------------------------------------------- // Copyright 2007 Jonathan Westhues // // This file is part of LDmicro. // // LDmicro is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // LDmicro is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with LDmicro. If not, see . //------ // // All the simple dialogs that just require a row of text boxes: timer name // and delay, counter name and count, move and arithmetic destination and // operands. Try to reuse code a bit. // Jonathan Westhues, Nov 2004 //----------------------------------------------------------------------------- #include "linuxUI.h" //#include #include #include #include "ldmicro.h" static HWID SimpleDialog; static HWID OkButton; static HWID CancelButton; #define MAX_BOXES 5 static HWID Textboxes[MAX_BOXES]; static HWID Labels[MAX_BOXES]; static LONG_PTR PrevAlnumOnlyProc[MAX_BOXES]; static LONG_PTR PrevNumOnlyProc[MAX_BOXES]; static BOOL NoCheckingOnBox[MAX_BOXES]; static BOOL SIMPLE_DIALOG_ACTIVE = FALSE; static SimpleDialogData SDdata; /// Simple dialog data flags #define SD_TIMER 0x0000001 #define SD_COUNTER 0x0000002 #define SD_CMP 0x0000003 #define SD_MOVE 0x0000004 #define SD_READ_ADC 0x0000005 #define SD_SET_PWM 0x0000006 #define SD_UART 0x0000007 #define SD_MATH 0x0000008 #define SD_SHIFT_REGISTER 0x0000009 #define SD_FORMATTED_STRING 0x0000010 #define SD_PERSIST 0x0000011 //----------------------------------------------------------------------------- // Don't allow any characters other than -A-Za-z0-9_ in the box. //----------------------------------------------------------------------------- static void MyAlnumOnlyProc (GtkEditable *editable, gchar *NewText, gint length, gint *position, gpointer data) { for (int i = 0; i < length; i++) { if (!(isalpha (NewText[i]) || NewText[i] == '_' || isdigit (NewText[i]) || NewText[i] == '\b' || NewText[i] == '\'' || NewText[i] == '-')) { g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text"); return; } } // if(msg == WM_CHAR) { // if(!(isalpha(wParam) || isdigit(wParam) || wParam == '_' || // wParam == '\b' || wParam == '-' || wParam == '\'')) // { // return 0; // } // } // int i; // for(i = 0; i < MAX_BOXES; i++) { // if(hwnd == Textboxes[i]) { // return CallWindowProc((WNDPROC)PrevAlnumOnlyProc[i], hwnd, msg, // wParam, lParam); // } // } // oops(); } //Set the closing parameters gboolean SimpleDialogClosing(GtkWidget *widget, GdkEvent *event, gpointer user_data) { SIMPLE_DIALOG_ACTIVE = FALSE; } //----------------------------------------------------------------------------- // Don't allow any characters other than -0-9. in the box. //----------------------------------------------------------------------------- static void MyNumOnlyProc (GtkEditable *editable, gchar *NewText, gint length, gint *position, gpointer data) { for (int i = 0; i < length; i++) { if (!(isdigit (NewText[i]) || NewText[i] == '\b' || NewText[i] == '.' || NewText[i] == '-')) { g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text"); return; } } // if(msg == WM_CHAR) { // if(!(isdigit(wParam) || wParam == '.' || wParam == '\b' // || wParam == '-')) // { // return 0; // } // } // int i; // for(i = 0; i < MAX_BOXES; i++) { // if(hwnd == Textboxes[i]) { // return CallWindowProc((WNDPROC)PrevNumOnlyProc[i], hwnd, msg, // wParam, lParam); // } // } // oops(); } static void MakeControls(int boxes, char **labels, DWORD fixedFontMask) { int i; // HDC hdc = GetDC(SimpleDialog); // SelectObject(hdc, MyNiceFont); // SIZE si; // int maxLen = 0; // for(i = 0; i < boxes; i++) { // GetTextExtentPoint32(hdc, labels[i], strlen(labels[i]), &si); // if(si.cx > maxLen) maxLen = si.cx; // } // int adj; // if(maxLen > 70) { // adj = maxLen - 70; // } else { // adj = 0; // } HWID grid = gtk_grid_new(); for(i = 0; i < boxes; i++) { // GetTextExtentPoint32(hdc, labels[i], strlen(labels[i]), &si); Labels[i] = gtk_label_new (labels[i]); // CreateWindowEx(0, WC_STATIC, labels[i], // WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, // (80 + adj) - si.cx - 4, 13 + i*30, si.cx, 21, // SimpleDialog, NULL, Instance, NULL); NiceFont(Labels[i]); gtk_grid_attach (GTK_GRID (grid), Labels[i], 0, i, 1, 1); Textboxes[i] = gtk_entry_new (); // CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, "", // WS_CHILD | ES_AUTOHSCROLL | WS_TABSTOP | WS_CLIPSIBLINGS | // WS_VISIBLE, // 80 + adj, 12 + 30*i, 120 - adj, 21, // SimpleDialog, NULL, Instance, NULL); if(fixedFontMask & (1 << i)) { FixedFont(Textboxes[i]); } else { NiceFont(Textboxes[i]); } gtk_grid_attach (GTK_GRID (grid), Textboxes[i], 1, i, 1, 1); } // ReleaseDC(SimpleDialog, hdc); OkButton = gtk_button_new_with_label (_("OK")); // CreateWindowEx(0, WC_BUTTON, _("OK"), // WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS | WS_VISIBLE | BS_DEFPUSHBUTTON, // 218, 11, 70, 23, SimpleDialog, NULL, Instance, NULL); NiceFont(OkButton); gtk_grid_attach (GTK_GRID (grid), OkButton, 2, 0, 1, 1); CancelButton = gtk_button_new_with_label(_("Cancel")); // CreateWindowEx(0, WC_BUTTON, _("Cancel"), // WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS | WS_VISIBLE, // 218, 41, 70, 23, SimpleDialog, NULL, Instance, NULL); NiceFont(CancelButton); gtk_grid_attach (GTK_GRID (grid), CancelButton, 2, 1, 1, 1); gtk_container_add(GTK_CONTAINER(SimpleDialog), grid); } void SimpleDialogWrapUp() { // if(!didCancel) for(int i = 0; i < SDdata.boxes; i++) { if(NoCheckingOnBox[i]) { // char get[64]; // SendMessage(Textboxes[i], WM_GETTEXT, 60, (LPARAM)get); char *get = (char*)gtk_entry_get_text (GTK_ENTRY(Textboxes[i])); strcpy(SDdata.dests[i], get); if (strlen(get) < 60) strcpy(SDdata.dests[i], get); else { strncpy(SDdata.dests[i], get, 60); SDdata.dests[i][60] = '\0'; } } else { char get[20]; // SendMessage(Textboxes[i], WM_GETTEXT, 15, (LPARAM)get); char *str = (char*)gtk_entry_get_text (GTK_ENTRY(Textboxes[i])); strcpy(get, str); if (strlen(str) < 15) strcpy(get, str); else { strncpy(get, str, 15); get[15] = '\0'; } if( (!strchr(get, '\'')) || (get[0] == '\'' && get[2] == '\'' && strlen(get)==3) ) { if(strlen(get) == 0) { Error(_("Empty textbox; not permitted.")); } else { strcpy(SDdata.dests[i], get); } } else { Error(_("Bad use of quotes: <%s>"), get); } } } switch(SDdata.uflag) { case SD_TIMER: { SDdata.str1[0] = 'T'; strcpy(SDdata.str1+1, SDdata.dests[0]); //g_print("%s, %s\n", SDdata.str1, SDdata.dests[0]); double del = atof(SDdata.dests[1]); if(del > 2140000) { // 2**31/1000, don't overflow signed int Error(_("Delay too long; maximum is 2**31 us.")); } else if(del <= 0) { Error(_("Delay cannot be zero or negative.")); } else { *SDdata.num1 = (int)(1000*del + 0.5); } break; } case SD_COUNTER: { *SDdata.num1 = atoi(SDdata.dests[1]); break; } case SD_CMP: { break; } case SD_MOVE: { break; } case SD_READ_ADC: { break; } case SD_SET_PWM: { *SDdata.num1 = atoi(SDdata.dests[1]); break; } case SD_UART: { break; } case SD_MATH: { break; } case SD_SHIFT_REGISTER: { *SDdata.num1 = atoi(SDdata.dests[1]); if(*SDdata.num1 <= 0 || *SDdata.num1 >= 200) { Error(_("Not a reasonable size for a shift register.")); *SDdata.num1 = 1; } break; } case SD_FORMATTED_STRING: { break; } case SD_PERSIST: { break; } } DestroyWindow(SimpleDialog); ProgramChanged(); SIMPLE_DIALOG_ACTIVE = FALSE; gtk_widget_set_sensitive (MainWindow, TRUE); } void SimpleDialogCancelProc() { DestroyWindow(SimpleDialog); ProgramChanged(); SIMPLE_DIALOG_ACTIVE = FALSE; gtk_widget_set_sensitive (MainWindow, TRUE); } static gboolean SimpleDialogKeyPressProc(HWID widget, GdkEventKey* event, gpointer data) { if(event -> keyval == GDK_KEY_Return) { // DialogDone = TRUE; SimpleDialogWrapUp(); } else if(event -> keyval == GDK_KEY_Escape) { // DialogDone = TRUE; // DialogCancel = TRUE; SimpleDialogCancelProc(); } return FALSE; } void ShowSimpleDialog(char *title, int boxes, char **labels, DWORD numOnlyMask, DWORD alnumOnlyMask, DWORD fixedFontMask, char **dests) { if(SIMPLE_DIALOG_ACTIVE) return; SIMPLE_DIALOG_ACTIVE = TRUE; BOOL didCancel = FALSE; if(boxes > MAX_BOXES) oops(); SimpleDialog = CreateWindowClient(GTK_WINDOW_TOPLEVEL, GDK_WINDOW_TYPE_HINT_NORMAL, title, 100, 100, 304, 15 + 30*(boxes < 2 ? 2 : boxes), GTK_WINDOW(MainWindow) ); // CreateWindowClient(0, "LDmicroDialog", title, // WS_OVERLAPPED | WS_SYSMENU, // 100, 100, 304, 15 + 30*(boxes < 2 ? 2 : boxes), NULL, NULL, // Instance, NULL); MakeControls(boxes, labels, fixedFontMask); int i; for(i = 0; i < boxes; i++) { // SendMessage(Textboxes[i], WM_SETTEXT, 0, (LPARAM)dests[i]); gtk_entry_set_text (GTK_ENTRY(Textboxes[i]), dests[i]); if(numOnlyMask & (1 << i)) { g_signal_connect (G_OBJECT(Textboxes[i]), "insert-text", G_CALLBACK(MyNumOnlyProc), NULL); // PrevNumOnlyProc[i] = SetWindowLongPtr(Textboxes[i], GWLP_WNDPROC, // (LONG_PTR)MyNumOnlyProc); } else if(alnumOnlyMask & (1 << i)) { g_signal_connect (G_OBJECT(Textboxes[i]), "insert-text", G_CALLBACK(MyAlnumOnlyProc), NULL); // PrevAlnumOnlyProc[i] = SetWindowLongPtr(Textboxes[i], GWLP_WNDPROC, // (LONG_PTR)MyAlnumOnlyProc); } } gtk_widget_show_all(SimpleDialog); g_signal_connect (CancelButton, "clicked", G_CALLBACK (SimpleDialogCancelProc), NULL); g_signal_connect (OkButton, "clicked", G_CALLBACK (SimpleDialogWrapUp), NULL); g_signal_connect (SimpleDialog, "key_press_event", G_CALLBACK (SimpleDialogKeyPressProc), NULL); g_signal_connect (SimpleDialog, "destroy_event", G_CALLBACK (SimpleDialogClosing), NULL); // EnableWindow(MainWindow, FALSE); // ShowWindow(SimpleDialog, TRUE); // SetFocus(Textboxes[0]); // SendMessage(Textboxes[0], EM_SETSEL, 0, -1); // MSG msg; // DWORD ret; // DialogDone = FALSE; // DialogCancel = FALSE; // while((ret = GetMessage(&msg, NULL, 0, 0)) && !DialogDone) { // if(msg.message == WM_KEYDOWN) { // if(msg.wParam == VK_RETURN) { // DialogDone = TRUE; // break; // } else if(msg.wParam == VK_ESCAPE) { // DialogDone = TRUE; // DialogCancel = TRUE; // break; // } // } // if(IsDialogMessage(SimpleDialog, &msg)) continue; // TranslateMessage(&msg); // DispatchMessage(&msg); // } // didCancel = DialogCancel; // EnableWindow(MainWindow, TRUE); // DestroyWindow(SimpleDialog); // return !didCancel; } void ShowTimerDialog(int which, int *delay, char *name) { char *s; switch(which) { case ELEM_TON: s = _("Turn-On Delay"); break; case ELEM_TOF: s = _("Turn-Off Delay"); break; case ELEM_RTO: s = _("Retentive Turn-On Delay"); break; default: oops(); break; } char *labels[] = { _("Name:"), _("Delay (ms):") }; char delBuf[16]; char nameBuf[16]; sprintf(delBuf, "%.3f", (*delay / 1000.0)); strcpy(nameBuf, name+1); char *dests[] = { nameBuf, delBuf }; if (SIMPLE_DIALOG_ACTIVE) return; SDdata.uflag = SD_TIMER; SDdata.boxes = 2; SDdata.str1 = name; SDdata.num1 = delay; SDdata.dests = new char*[2]; SDdata.dests[0] = new char[16]; SDdata.dests[1] = new char[16]; sprintf(SDdata.dests[1], "%.3f", (*delay / 1000.0)); strcpy(SDdata.dests[0], name+1); ShowSimpleDialog(s, 2, labels, (1 << 1), (1 << 0), (1 << 0), dests); } void ShowCounterDialog(int which, int *maxV, char *name) { char *title; switch(which) { case ELEM_CTU: title = _("Count Up"); break; case ELEM_CTD: title = _("Count Down"); break; case ELEM_CTC: title = _("Circular Counter"); break; default: oops(); } char *labels[] = { _("Name:"), (which == ELEM_CTC ? _("Max value:") : _("True if >= :")) }; char maxS[128]; sprintf(maxS, "%d", *maxV); char *dests[] = { name+1, maxS }; if (SIMPLE_DIALOG_ACTIVE) return; SDdata.uflag = SD_COUNTER; SDdata.boxes = 2; SDdata.str1 = name; SDdata.num1 = maxV; SDdata.dests = new char*[2]; SDdata.dests[0] = name+1; SDdata.dests[1] = new char[128]; sprintf(SDdata.dests[1], "%d", *maxV); ShowSimpleDialog(title, 2, labels, 0x2, 0x1, 0x1, dests); } void ShowCmpDialog(int which, char *op1, char *op2) { char *title; char *l2; switch(which) { case ELEM_EQU: title = _("If Equals"); l2 = "= :"; break; case ELEM_NEQ: title = _("If Not Equals"); l2 = "/= :"; break; case ELEM_GRT: title = _("If Greater Than"); l2 = "> :"; break; case ELEM_GEQ: title = _("If Greater Than or Equal To"); l2 = ">= :"; break; case ELEM_LES: title = _("If Less Than"); l2 = "< :"; break; case ELEM_LEQ: title = _("If Less Than or Equal To"); l2 = "<= :"; break; default: oops(); } char *labels[] = { _("'Closed' if:"), l2 }; char *dests[] = { op1, op2 }; if (SIMPLE_DIALOG_ACTIVE) return; SDdata.uflag = SD_CMP; SDdata.boxes = 2; SDdata.dests = new char*[2]; SDdata.dests[0] = op1; SDdata.dests[1] = op2; ShowSimpleDialog(title, 2, labels, 0, 0x3, 0x3, dests); } void ShowMoveDialog(char *dest, char *src) { char *labels[] = { _("Destination:"), _("Source:") }; char *dests[] = { dest, src }; if (SIMPLE_DIALOG_ACTIVE) return; SDdata.uflag = SD_MOVE; SDdata.boxes = 2; SDdata.dests = new char*[2]; SDdata.dests[0] = dest; SDdata.dests[1] = src; ShowSimpleDialog(_("Move"), 2, labels, 0, 0x3, 0x3, dests); } void ShowReadAdcDialog(char *name) { char *labels[] = { _("Destination:") }; char *dests[] = { name }; if (SIMPLE_DIALOG_ACTIVE) return; SDdata.uflag = SD_READ_ADC; SDdata.boxes = 1; SDdata.dests = new char*[1]; SDdata.dests[0] = name; ShowSimpleDialog(_("Read A/D Converter"), 1, labels, 0, 0x1, 0x1, dests); } void ShowSetPwmDialog(char *name, int *targetFreq) { char freq[100]; sprintf(freq, "%d", *targetFreq); char *labels[] = { _("Duty cycle var:"), _("Frequency (Hz):") }; char *dests[] = { name, freq }; if (SIMPLE_DIALOG_ACTIVE) return; SDdata.uflag = SD_SET_PWM; SDdata.boxes = 2; SDdata.num1 = targetFreq; SDdata.dests = new char*[2]; SDdata.dests[0] = name; SDdata.dests[1] = new char[100]; sprintf(SDdata.dests[1], "%d", *targetFreq); ShowSimpleDialog(_("Set PWM Duty Cycle"), 2, labels, 0x2, 0x1, 0x1, dests); } void ShowUartDialog(int which, char *name) { char *labels[] = { (which == ELEM_UART_RECV) ? _("Destination:") : _("Source:") }; char *dests[] = { name }; if (SIMPLE_DIALOG_ACTIVE) return; SDdata.uflag = SD_UART; SDdata.boxes = 1; SDdata.dests = new char*[2]; SDdata.dests[0] = name; ShowSimpleDialog((which == ELEM_UART_RECV) ? _("Receive from UART") : _("Send to UART"), 1, labels, 0, 0x1, 0x1, dests); } void ShowMathDialog(int which, char *dest, char *op1, char *op2) { char *l2, *title; if(which == ELEM_ADD) { l2 = "+ :"; title = _("Add"); } else if(which == ELEM_SUB) { l2 = "- :"; title = _("Subtract"); } else if(which == ELEM_MUL) { l2 = "* :"; title = _("Multiply"); } else if(which == ELEM_DIV) { l2 = "/ :"; title = _("Divide"); } else oops(); char *labels[] = { _("Destination:"), _("is set := :"), l2 }; char *dests[] = { dest, op1, op2 }; if (SIMPLE_DIALOG_ACTIVE) return; SDdata.uflag = SD_MATH; SDdata.boxes = 3; SDdata.dests = new char*[3]; SDdata.dests[0] = dest; SDdata.dests[1] = op1; SDdata.dests[2] = op2; ShowSimpleDialog(title, 3, labels, 0, 0x7, 0x7, dests); } void ShowShiftRegisterDialog(char *name, int *stages) { char stagesStr[20]; sprintf(stagesStr, "%d", *stages); char *labels[] = { _("Name:"), _("Stages:") }; char *dests[] = { name, stagesStr }; if (SIMPLE_DIALOG_ACTIVE) return; SDdata.uflag = SD_SHIFT_REGISTER; SDdata.boxes = 2; SDdata.num1 = stages; SDdata.dests = new char*[2]; SDdata.dests[0] = name; SDdata.dests[1] = new char[20]; sprintf(SDdata.dests[1], "%d", *stages); ShowSimpleDialog(_("Shift Register"), 2, labels, 0x2, 0x1, 0x1, dests); } void ShowFormattedStringDialog(char *var, char *string) { char *labels[] = { _("Variable:"), _("String:") }; char *dests[] = { var, string }; if (SIMPLE_DIALOG_ACTIVE) return; SDdata.uflag = SD_FORMATTED_STRING; SDdata.boxes = 2; SDdata.dests = new char*[2]; SDdata.dests[0] = var; SDdata.dests[1] = string; NoCheckingOnBox[0] = TRUE; NoCheckingOnBox[1] = TRUE; ShowSimpleDialog(_("Formatted String Over UART"), 2, labels, 0x0, 0x1, 0x3, dests); NoCheckingOnBox[0] = FALSE; NoCheckingOnBox[1] = FALSE; } void ShowPersistDialog(char *var) { char *labels[] = { _("Variable:") }; char *dests[] = { var }; if (SIMPLE_DIALOG_ACTIVE) return; SDdata.uflag = SD_PERSIST; SDdata.boxes = 1; SDdata.dests = new char*[1]; SDdata.dests[0] = var; ShowSimpleDialog(_("Make Persistent"), 1, labels, 0, 1, 1, dests); }