📄 thedialog.cpp
字号:
//TheDialog.cpp, Copyright (c) 2001, 2002, 2003, 2004, 2005 R.Lackner
//Operating system independent code for dialog boxes
//
// This file is part of RLPlot.
//
// RLPlot 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 2 of the License, or
// (at your option) any later version.
//
// RLPlot 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 RLPlot; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include "rlplot.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "TheDialog.h"
extern tag_Units Units[];
extern char TmpTxt[];
extern Default defs;
extern GraphObj *CurrGO;
extern EditText *CurrText; //current EditText object
extern RECT rTxtCur; //text cursor position and direction
extern UndoObj Undo;
char *WWWbrowser = 0L;
char *LoadFile = 0L;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// internal declarations
static int xbase = 2;
static int ybase = 2;
int dlgtxtheight = 10;
static unsigned long DlgBGcolor = 0x00e0e0e0L;
static unsigned long DlgBGhigh = 0x00e8e8e8L;
TextDEF DlgText = {0x00000000L, 0x00ffffffL, 4.0, 0.0f, 0.0f, 0,
TXA_HLEFT | TXA_VTOP, TXM_TRANSPARENT, TXS_NORMAL, FONT_HELVETICA, 0L};
//prototypes: WinSpec.cpp
void *CreateDlgWnd(char *title, int x, int y, int width, int height, tag_DlgObj *d, DWORD flags);
//The dialog object which just has the input focus
Dialog *DialogFocus = 0L;
Dialog *DialogDefault = 0L;
Dialog *DialogTabStop = 0L;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Base classes to dialog items
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DlgRoot::DlgRoot(DlgInfo *tmpl)
{
int i;
RECT rc;
dlg = 0L; flags = 0L; tabstops = 0L;
DlgText.iSize = dlgtxtheight; DlgText.ColBg = DlgBGcolor;
type = NONE; Id = -2; cContinue = 0;
bActive = false; Result = -1; c_go = CurrGO;
CurrDisp = 0L; oldFocus = DialogFocus; DialogFocus = 0L;
oldDefault = DialogDefault; oldTabStop = DialogTabStop;
if(tmpl) {
//count number of items first, then allocate memory
for(cDlgs=1;!(tmpl[cDlgs-1].flags & LASTOBJ); cDlgs++);
dlg = (DlgTmpl **)calloc(cDlgs+1, sizeof(DlgTmpl*));
tabstops =(Dialog**)calloc(cDlgs, sizeof(Dialog*));
if(dlg) for (i = 0; i < cDlgs; i++) {
dlg[i] = (DlgTmpl *)malloc(sizeof(DlgTmpl));
if(dlg[i]) {
dlg[i]->id = tmpl[i].id;
dlg[i]->next = tmpl[i].next;
dlg[i]->first = tmpl[i].first;
dlg[i]->flags = tmpl[i].flags;
rc.left = tmpl[i].x * xbase;
rc.right = rc.left + tmpl[i].w * xbase;
rc.top = tmpl[i].y * ybase;
rc.bottom = rc.top + tmpl[i].h * ybase;
//an item appearing in the following list should have a corresponding
// entry in the list of ~DlgRoot()
switch(tmpl[i].type) {
case PUSHBUTTON:
dlg[i]->dialog = new PushButton(this, &tmpl[i],rc,(char*)tmpl[i].ptype);
break;
case TEXTBOX:
dlg[i]->dialog = new TextBox(this, &tmpl[i],rc,(char*)tmpl[i].ptype);
break;
case ARROWBUTT:
dlg[i]->dialog = new ArrowButton(this, &tmpl[i],rc,(int*)tmpl[i].ptype);
break;
case COLBUTTON:
dlg[i]->dialog = new ColorButton(this, &tmpl[i],rc, (unsigned long)tmpl[i].ptype);
break;
case FILLBUTTON:
dlg[i]->dialog = new FillButton(this, &tmpl[i],rc, (FillDEF *)tmpl[i].ptype);
break;
case SHADE3D:
dlg[i]->dialog = new Shade3D(this, &tmpl[i],rc, (FillDEF *)tmpl[i].ptype);
break;
case LINEBUTT:
dlg[i]->dialog = new LineButton(this, &tmpl[i],rc, (LineDEF *)tmpl[i].ptype);
break;
case SYMBUTT:
dlg[i]->dialog = new SymButton(this, &tmpl[i],rc, (Symbol **)tmpl[i].ptype);
break;
case FILLRADIO:
dlg[i]->dialog = new FillRadioButt(this, &tmpl[i],rc, *((unsigned int*)tmpl[i].ptype));
break;
case SYMRADIO:
dlg[i]->dialog = new SymRadioButt(this, &tmpl[i],rc, (int*)tmpl[i].ptype);
break;
case CHECKBOX:
dlg[i]->dialog = new CheckBox(this, &tmpl[i],rc,(char*)tmpl[i].ptype);
break;
case CHECKPIN:
dlg[i]->dialog = new CheckPin(this, &tmpl[i],rc);
break;
case TRASH:
dlg[i]->dialog = new Trash(this, &tmpl[i],rc);
break;
case CONFIG:
dlg[i]->dialog = new Config(this, &tmpl[i],rc);
break;
case RADIO0: case RADIO1: case RADIO2:
dlg[i]->dialog = new RadioButton(this, &tmpl[i],rc,(char*)tmpl[i].ptype);
break;
case LTEXT: case RTEXT: case CTEXT:
dlg[i]->dialog = new Text(this, &tmpl[i],rc,(char*)tmpl[i].ptype);
break;
case EDTEXT:
dlg[i]->dialog = new InputText(this, &tmpl[i],rc,(char*)tmpl[i].ptype);
break;
case RANGEINPUT:
dlg[i]->dialog = new RangeInput(this, &tmpl[i],rc,(char*)tmpl[i].ptype);
break;
case EDVAL1:
dlg[i]->dialog = new InputValue(this, &tmpl[i],rc,(double*)tmpl[i].ptype);
break;
case INCDECVAL1:
dlg[i]->dialog = new IncDecValue(this, &tmpl[i],rc,(double*)tmpl[i].ptype);
break;
case TXTHSP:
dlg[i]->dialog = new TxtHSP(this, &tmpl[i],rc, (int*)tmpl[i].ptype);
break;
case VSCROLL:
dlg[i]->dialog = new ScrollBar(this, &tmpl[i],rc, true);
break;
case HSCROLL:
dlg[i]->dialog = new ScrollBar(this, &tmpl[i],rc, false);
break;
case ICON:
dlg[i]->dialog = new Icon(this, &tmpl[i],rc, (int*)tmpl[i].ptype);
break;
case GROUP:
dlg[i]->dialog = new Group(this, &tmpl[i], rc);
break;
case GROUPBOX:
dlg[i]->dialog = new GroupBox(this, &tmpl[i],rc, (char*)tmpl[i].ptype);
break;
case SHEET:
dlg[i]->dialog = new TabSheet(this, &tmpl[i],rc, (TabSHEET *)tmpl[i].ptype);
break;
case ODBUTTON:
dlg[i]->dialog = new ODbutton(this, &tmpl[i],rc, tmpl[i].ptype);
break;
case LISTBOX1:
dlg[i]->dialog = new Listbox(this, &tmpl[i],rc, (char**)tmpl[i].ptype);
break;
case TREEVIEW:
dlg[i]->dialog = new Treeview(this, &tmpl[i],rc, (GraphObj*)tmpl[i].ptype);
break;
case LINEPAT:
dlg[i]->dialog = new LinePat(this, &tmpl[i],rc, (LineDEF *)tmpl[i].ptype);
break;
default:
dlg[i]->dialog = NULL;
}
}
else break;
}
}
}
DlgRoot::~DlgRoot()
{
int i;
if(dlg){
for (i = 0; dlg[i] && i < cDlgs; i++) {
//we need to delete each object using a cast on its proper type
//to call the proper destructor
if(dlg[i]->dialog){
switch(dlg[i]->dialog->type) {
case PUSHBUTTON: delete((PushButton*)dlg[i]->dialog); break;
case TEXTBOX: delete((TextBox*)dlg[i]->dialog); break;
case ARROWBUTT: delete((ArrowButton*)dlg[i]->dialog); break;
case COLBUTTON: delete((ColorButton*)dlg[i]->dialog); break;
case FILLBUTTON: delete((FillButton*)dlg[i]->dialog); break;
case SHADE3D: delete((Shade3D*)dlg[i]->dialog); break;
case LINEBUTT: delete((LineButton*)dlg[i]->dialog); break;
case SYMBUTT: delete((SymButton*)dlg[i]->dialog); break;
case FILLRADIO: delete((FillRadioButt*)dlg[i]->dialog); break;
case SYMRADIO: delete((SymRadioButt*)dlg[i]->dialog); break;
case CHECKBOX: delete((CheckBox*)dlg[i]->dialog); break;
case CHECKPIN: delete((CheckPin*)dlg[i]->dialog); break;
case TRASH: delete((Trash*)dlg[i]->dialog); break;
case CONFIG: delete((Config*)dlg[i]->dialog); break;
case RADIO0: case RADIO1:
case RADIO2: delete((RadioButton*)dlg[i]->dialog); break;
case LTEXT: case RTEXT:
case CTEXT: delete((Text*)dlg[i]->dialog); break;
case EDTEXT: delete((InputText*)dlg[i]->dialog); break;
case RANGEINPUT: delete((RangeInput*)dlg[i]->dialog); break;
case EDVAL1: delete((InputValue*)dlg[i]->dialog); break;
case INCDECVAL1: delete((IncDecValue*)dlg[i]->dialog); break;
case TXTHSP: delete((TxtHSP*)dlg[i]->dialog); break;
case HSCROLL:
case VSCROLL: delete((ScrollBar*)dlg[i]->dialog); break;
case ICON: delete((Icon*)dlg[i]->dialog); break;
case GROUP: delete((Group*)dlg[i]->dialog); break;
case GROUPBOX: delete((GroupBox*)dlg[i]->dialog); break;
case SHEET: delete((TabSheet*)dlg[i]->dialog); break;
case ODBUTTON: delete((ODbutton*)dlg[i]->dialog); break;
case LISTBOX1: delete((Listbox*)dlg[i]->dialog); break;
case TREEVIEW: delete((Treeview*)dlg[i]->dialog); break;
case LINEPAT: delete((LinePat*)dlg[i]->dialog); break;
default:
//DEBUG: we should issue a message that an unknown item is
// deleted: this might result in a memory leak;
InfoBox("unknown dialog object found\nin \"DlgRoot::~DlgRoot()\"");
delete(dlg[i]->dialog);
break;
}
}
free(dlg[i]);
}
free(dlg);
}
if(tabstops) free(tabstops);
DialogFocus = oldFocus; DialogDefault = oldDefault;
DialogTabStop = oldTabStop; CurrGO = c_go;
}
bool
DlgRoot::Command(int cmd, void *tmpl, anyOutput *o)
{
Dialog *d;
int i, j;
RECT rc;
switch (cmd) {
case CMD_UNDO:
if(CurrDisp) {
Undo.Restore(false, CurrDisp);
DoPlot(CurrDisp);
}
return true;
case CMD_REDRAW:
if(CurrDisp) {
CurrDisp->Erase(DlgBGcolor); DoPlot(CurrDisp);
CurrDisp->GetSize(&rc); CurrDisp->UpdateRect(&rc, false);
}
return true;
case CMD_MOUSE_EVENT:
mev = (MouseEvent *) tmpl;
switch(mev->Action) {
case MOUSE_LBDOWN:
bActive = true;
case MOUSE_MOVE:
if(!(mev->StateFlags & 1))return false;
//track mouse and display controls accordingly
if(bActive)ForEach(CMD_MOUSE_EVENT, 0, o);
return true;
case MOUSE_LBDOUBLECLICK:
ForEach(CMD_MOUSE_EVENT, 0, o);
bActive = false; //skip next event (LB up);
return true;
case MOUSE_LBUP:
if(bActive)ForEach(CMD_LBUP, 0, o);
return true;
}
return true;
case CMD_ENDDIALOG:
d = (Dialog *)tmpl;
if(d) {
Result = d->Id; // end dialog by object
cContinue = 0;
}
else if(cContinue >0) {
cContinue--;
return true; // no end upon killing the focus
}
else {
Result = 0; // end dialog with closebox or loose focus
}
return true;
case CMD_CONTINUE:
cContinue++;
return true;
case CMD_TABDLG:
if(tabstops) for (i = 0; i < cDlgs; i++)
if(!tabstops[i] || tabstops[i] == (Dialog*)tmpl) {
tabstops[i] = (Dialog*)tmpl;
return true;
}
return false;
case CMD_NOTABDLG:
if(tabstops) for (i = j = 0; i < cDlgs; i++) {
if(tabstops[i] == (Dialog*)tmpl) tabstops[i] = 0L;
if(tabstops[i]) tabstops[j++] = tabstops[i];
}
return true;
case CMD_TAB:
HideTextCursor();
if(tabstops && DialogTabStop) {
for(i = 0; tabstops[i] && tabstops[i] != DialogTabStop && i < cDlgs; i++);
if(tabstops[i]) i++;
if(!tabstops[i]) i = 0;
switch(tabstops[i]->type) {
case PUSHBUTTON:
d = DialogDefault;
DialogTabStop = DialogDefault = tabstops[i];
d->DoPlot(o);
DialogDefault->DoPlot(o);
break;
case EDTEXT: case EDVAL1: case RANGEINPUT:
case INCDECVAL1:
DialogTabStop = DialogFocus = tabstops[i];
if((InputText*)DialogFocus->bActive)
((InputText*)DialogFocus)->Activate(DialogFocus->Id, true);
else Command(cmd, tmpl, o);
break;
}
}
return true;
case CMD_SHTAB:
HideTextCursor();
if(tabstops && DialogTabStop) {
for(j = 0; tabstops[j]; j++);
for(i = j-1; tabstops[i] != DialogTabStop && i; i--);
i = i >0 ? i-1 : j-1;
switch(tabstops[i]->type) {
case PUSHBUTTON:
d = DialogDefault;
DialogTabStop = DialogDefault = tabstops[i];
d->DoPlot(o);
DialogDefault->DoPlot(o);
break;
case EDTEXT: case EDVAL1: case INCDECVAL1:
case RANGEINPUT:
DialogTabStop = DialogFocus = tabstops[i];
((InputText*)DialogFocus)->Activate(DialogFocus->Id, true);
break;
}
}
return true;
case CMD_CURRUP: case CMD_CURRDOWN:
if(DialogFocus && DialogFocus->type == TEXTBOX)
return DialogFocus->Command(cmd, tmpl, o);
else return CurUpDown(cmd);
case CMD_CURRLEFT: case CMD_CURRIGHT: case CMD_DELETE:
case CMD_POS_FIRST: case CMD_POS_LAST: case CMD_SHIFTLEFT:
case CMD_SHIFTRIGHT: case CMD_COPY: case CMD_PASTE:
Undo.SetDisp(CurrDisp);
bActive = true;
if(DialogFocus)return DialogFocus->Command(cmd, tmpl, CurrDisp);
else return false;
case CMD_ADDCHAR:
if(!tmpl) return false;
bActive = true;
if(*((int*)tmpl) == 27) { //Esc
HideCopyMark();
for (i = 0; dlg[i] && i < cDlgs; i++)
if(dlg[i]->dialog) dlg[i]->dialog->Command(cmd, tmpl, o);
return Command(CMD_REDRAW, 0L, 0L);
}
if(DialogDefault && *((int*)tmpl) == 0x0d){ //return pressed
HideTextCursor();
return DialogDefault->Command(cmd, tmpl, o);
}
if(DialogFocus)return DialogFocus->Command(cmd, tmpl, o);
else return false;
case CMD_UNLOCK:
CurrDisp = 0L;
for(i = 0; i < cDlgs; i++)
if(dlg[i] && dlg[i]->dialog) dlg[i]->dialog->Command(CMD_UNLOCK, 0L, 0L);
break;
}
return false;
}
void
DlgRoot::DoPlot(anyOutput *o)
{
int i;
HideCopyMark();
if(tabstops) for(i = 0; i < cDlgs; tabstops[i++] = 0);
if(o)CurrDisp = o;
if(CurrDisp) {
CurrDisp->SetTextSpec(&DlgText);
ForEach(CMD_DOPLOT, 0, CurrDisp);
}
}
bool
DlgRoot::CurUpDown(int cmd)
{
int i, ya, yb, dy;
Dialog *above=0L, *below=0L;
ya = -1000; yb = 10000;
if(DialogFocus && tabstops && DialogTabStop == DialogFocus) {
for(i = 0; tabstops[i] && i < cDlgs; i++) {
if(tabstops[i] != DialogTabStop) {
switch(tabstops[i]->type) {
case EDVAL1: case INCDECVAL1: case EDTEXT: case RANGEINPUT:
if(rTxtCur.left > tabstops[i]->cr.left &&
rTxtCur.right < tabstops[i]->cr.right) {
if((dy = (tabstops[i]->cr.top - rTxtCur.top))< 0) {
if(dy > ya) {
ya = dy; above = tabstops[i];
}
}
else {
if(dy < yb) {
yb = dy; below = tabstops[i];
}
}
}
break;
}
}
}
switch(cmd) {
case CMD_CURRUP:
if(above) {
above->Select(rTxtCur.left, (above->cr.top + above->cr.bottom)>>1, CurrDisp);
}
break;
case CMD_CURRDOWN:
if(below) {
below->Select(rTxtCur.left, (below->cr.top + below->cr.bottom)>>1, CurrDisp);
}
break;
}
}
return false;
}
bool
DlgRoot::GetColor(int id, DWORD *color)
{
int i;
i = FindIndex(id);
if(i && dlg[i]) return dlg[i]->dialog->GetColor(id, color);
return false;
}
void
DlgRoot::SetColor(int id, DWORD color)
{
int i;
i = FindIndex(id);
if(i && dlg[i]) {
dlg[i]->dialog->SetColor(id, color);
if(CurrDisp && !(dlg[i]->dialog->flags & HIDDEN)) dlg[i]->dialog->DoPlot(CurrDisp);
}
}
bool
DlgRoot::GetValue(int id, double *val)
{
int i;
i = FindIndex(id);
if(i && dlg[i]) return dlg[i]->dialog->GetValue(id, val);
return false;
}
bool
DlgRoot::GetInt(int id, int *val)
{
int i;
i = FindIndex(id);
if(i && dlg[i]) return dlg[i]->dialog->GetInt(id, val);
return false;
}
bool
DlgRoot::SetCheck(int id, anyOutput *o, bool state)
{
int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -