1
/**********************************************************************
2
optswx.cpp - Constructs wxWidgets Option controls from description text
4
Copyright (C) 2006 by Chris Morley
6
This file is part of the Open Babel project.
7
For more information, see <http://openbabel.sourceforge.net/>
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation version 2 of the License.
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
17
***********************************************************************/
18
#include "babelconfig.h"
24
////////////////////////////////////////////////////
25
DynOptionswx::~DynOptionswx()
28
void DynOptionswx::Clear()
30
OMapType::iterator itr;
31
for(itr=OptionMap.begin();itr!=OptionMap.end();++itr)
33
sizer->Detach(itr->second);
34
(itr->second)->Destroy();
37
std::vector<wxSizer*>::iterator itrs;
38
for(itrs=Sizers.begin();itrs!=Sizers.end();++itrs)
46
bool DynOptionswx::Construct(const char* OptionsText, const char* StartText, int MultiCharFilter)
48
//Looks for "options" (case-insensitive)
49
//If StartText is not NULL it must precede "options" on the same line and
50
//not be part of a longer word
53
bool NextIsRadio=false;
54
char* pNewStr = new char[strlen(OptionsText)+1];
55
strcpy(pNewStr,OptionsText); //Make a working copy
58
bool OptionsFound=false;
65
p=strcasestr(p,StartText);//locate StartText
67
p += strlen(StartText);
68
}while(isalpha(*p));//next char is not a letter or number
70
lineend=strchr(p,'\n');
72
if(p && (p=strcasestr(p,"option")) && (!lineend || p<lineend))
76
p = strchr(p,'\n')+1; //options start on next line
77
while(p && *p && *p!='\n') //loop for all options until blank line
80
while(*p && !isalnum(*(p++))); //skip space and punctuation
86
//Filter on whether option is single or multicharacter
87
//MultiCharFilter == 0 Display all options
88
//MultiCharFilter == 1 Display only single char options
89
//MultiCharFilter == 2 Display only multi char options
90
if((MultiCharFilter==1 && oname.size()>1)
91
|| (MultiCharFilter==2 && oname.size()==1))
94
if(p) ++p; //to next line
98
while(isspace(*p++));//skip white space
99
while(ispunct(*(--p)) && *p != '-')
101
//If first non-white space character after option char is punctuation(except for '-')
102
//Provide an edit control rather than a checkbox
119
char* ptemp = strchr(p, endch);
123
while(isspace(*p++));//skip white space
126
p--; //so not to lose first char of caption
128
while(!isalnum(*(++p))); //skip space and punctuation
130
char* pCaption = p-1;
133
*p++ ='\0'; //mark end of this option's text
140
if(pdef=strcasestr(pCaption,"default"))
142
//Put the next word in the editbox
143
char* tok=strtok(pdef," :-\t</\"\'");
144
pdefWord = strtok(NULL," :-</\t;,\"\'>");
146
//delete caption after default or after <default etc
148
while(isspace(*(--pdef)));
149
if(!strpbrk(pdef,"([<{-;")) pdef++ ;
152
wxStaticText* pEdCaption = new wxStaticText(parent,wxID_STATIC,pCaption);
153
OptionMap.push_back(std::make_pair(wxString(),pEdCaption));//string is empty for a caption: not an option
155
//Edit boxes for multicharacter options are larger
156
const int EDWIDTH = oname.size()>1? 60 : 40;
159
//Make a large edit box on the next line if last char is of the caption is :
160
bool BigEdit =(pCaption[strlen(pCaption)-1] == ':');
163
sizer->Add(pEdCaption,0,wxEXPAND|wxTOP,FOUR);
164
while(ProvideEditCtl--)
166
pEd = new wxTextCtrl(parent,wxID_ANY,wxEmptyString,
167
wxDefaultPosition,wxSize(EDWIDTH,16));
168
OptionMap.push_back(std::make_pair(oname,pEd));
170
oname = ' ' + oname;//editboxes except the first have name preceded by one or more spaces
172
sizer->Add(pEd,0,wxEXPAND|wxTOP,ONE);
176
wxBoxSizer* pEdSizer = new wxBoxSizer(wxHORIZONTAL);
177
while(ProvideEditCtl--)
179
pEd = new wxTextCtrl(parent,wxID_ANY,wxEmptyString,
180
wxDefaultPosition,wxSize(EDWIDTH,16));
181
OptionMap.push_back(std::make_pair(oname,pEd));
183
oname = ' ' + oname;//editboxes except the first have name preceded by one or more spaces
184
pEdSizer->Add(pEd,0);
186
pEdSizer->Add(pEdCaption,1,wxLEFT|wxALIGN_CENTER_VERTICAL,FOUR);
187
sizer->Add(pEdSizer,0,wxEXPAND|wxTOP,FOUR);
188
Sizers.push_back(pEdSizer);
190
pEd->AppendText(pdefWord);
194
// Checkbox, or radio button ("or" is the last word in the caption && no letters after " or")
197
//First see if should be checked
198
//If 'default appears in caption set the checkbox unless it is followed
199
//by one of 'no' 'not' or 'none'
200
char* pdef=strcasestr(pCaption,"default");
201
bool SetChk=(pdef!=NULL);
203
strcasecmp(pdef,"no") && !strcasecmp(pdef,"not") && strcasecmp(pdef,"none");
205
char* por=strcasestr(pCaption," or");
206
bool HasOr = (por && !strpbrk(por+3,"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
208
if(NextIsRadio || HasOr)
210
unsigned int style = NextIsRadio ? 0 : wxRB_GROUP; //Style only on first radiobutton
211
pChk = new wxRadioButton(parent,wxID_ANY,pCaption,
212
wxDefaultPosition, wxDefaultSize, style);
214
((wxRadioButton*)pChk)->SetValue(SetChk);
218
pChk = new wxCheckBox(parent,wxID_ANY,pCaption);
219
((wxCheckBox*)pChk)->SetValue(SetChk);
222
OptionMap.push_back(std::make_pair(oname,pChk));
223
sizer->Add(pChk,0,wxEXPAND|wxTOP,FOUR);
229
wxStaticLine* pLine = new wxStaticLine(parent);
230
sizer->Add(pLine,0,wxTOP|wxEXPAND,FOUR);
231
OptionMap.push_back(std::make_pair(wxString(),pLine));//empty string
237
//////////////////////////////////////////////////////////
240
int DynOptionswx::SetOptions(OpenBabel::OBConversion& Conv, OpenBabel::OBConversion::Option_type opttyp)
242
//Now sets options directly in OBConversion
244
OMapType::iterator itr;
245
for (itr = OptionMap.begin(); itr != OptionMap.end(); ++itr)
247
if(itr->first.empty()) continue; //just a caption or a line
248
wxCheckBox* pChk = dynamic_cast<wxCheckBox*> (itr->second);
251
if(pChk->IsChecked())
253
Conv.AddOption(itr->first, opttyp);
259
wxRadioButton* pRadio = dynamic_cast<wxRadioButton*> (itr->second);
262
if(pRadio->GetValue())
264
Conv.AddOption(itr->first, opttyp);
270
wxTextCtrl* pText = dynamic_cast<wxTextCtrl*> (itr->second);
273
wxString txt = pText->GetValue();
274
if(txt.IsEmpty()) continue;
275
wxString oname = itr->first;
277
//Get the contents of subsequent editboxes
278
OMapType::iterator itr2 = itr;
279
while(++itr2!= OptionMap.end())
281
if(itr2->first[0]!=' ') //subsequent editboxes have the name preceded by a space
283
txt = txt + ' ' + static_cast<wxTextCtrl*>(itr2->second)->GetValue();
286
Conv.AddOption(oname, opttyp, txt);
295
//////////////////////////////////////////////////////////
296
char* DynOptionswx::strcasestr(const char* haystack, const char* needle)
298
//Adapted from http://primates.ximian.com/~fejj/strlib.c
299
register unsigned char *h, *n, *hc, *nc;
300
size_t needlelen = strlen (needle);
302
return (char *) haystack;
304
h=(unsigned char *)haystack;
305
n=(unsigned char *)needle;
306
while (*(h + needlelen - 1))
308
if (tolower(*h) == tolower(*n))
310
for (hc = h + 1, nc = n + 1; *hc && *nc; hc++, nc++)
311
if (tolower(*hc) != tolower(*nc))