Back to index

plt-scheme  4.2.1
Choice.cc
Go to the documentation of this file.
00001 /*                                                      -*- C++ -*-
00002  *
00003  * Purpose: choice panel item
00004  *
00005  * Authors: Markus Holzem and Julian Smart
00006  *
00007  * Copyright: (C) 2004-2009 PLT Scheme Inc.
00008  * Copyright: (C) 1995, AIAI, University of Edinburgh (Julian)
00009  * Copyright: (C) 1995, GNU (Markus)
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00024  * 02110-1301 USA.
00025  */
00026 
00027 #ifdef __GNUG__
00028 #pragma implementation "Choice.h"
00029 #endif
00030 
00031 #define  Uses_XtIntrinsic
00032 #define  Uses_wxChoice
00033 #define  Uses_wxMenu
00034 #include "wx.h"
00035 #define  Uses_ArrowWidget
00036 #define  Uses_TraversingEnforcerWidget
00037 #define  Uses_LabelWidget
00038 #include "widgets.h"
00039 
00040 char *wxchoice_unprotect_amp(char *s);
00041 
00042 //-----------------------------------------------------------------------------
00043 // create and destroy button
00044 //-----------------------------------------------------------------------------
00045 
00046 wxChoice::wxChoice(wxPanel *panel, wxFunction function, char *label,
00047                  int x, int y, int width, int height,
00048                  int n, char *choices[], long style, wxFont *_font, char *name) : wxItem(_font)
00049 {
00050   wxMenu *naya;
00051 
00052   __type = wxTYPE_CHOICE;
00053   
00054   naya = DEBUG_NEW wxMenu(NULL, (wxFunction)&(wxChoice::MenuEventCallback), font);
00055   choice_menu = naya;
00056   num_choices = 0;
00057   selection   = -1;
00058   
00059   Create(panel, function, label, x, y, width, height, n, choices, style, name);
00060 }
00061 
00062 Bool wxChoice::Create(wxPanel *panel, wxFunction function, char *label,
00063                     int x, int y, int width, int height,
00064                     int n, char *choices[], long style, char *name)
00065 {
00066     wxWindow_Xintern *ph;
00067     Bool vert;
00068     Widget button, wgt;
00069 
00070     ChainToPanel(panel, style, name);
00071 
00072     if (style & wxVERTICAL_LABEL)
00073       vert = 1;
00074     else if (style & wxHORIZONTAL_LABEL)
00075       vert = 0;
00076     else
00077       vert = (panel->GetLabelPosition() == wxVERTICAL);
00078 
00079     label = wxGetCtlLabel(label);
00080 
00081     ph = parent->GetHandle();
00082 
00083     // create frame
00084     wgt = XtVaCreateWidget
00085        (name, xfwfTraversingEnforcerWidgetClass, ph->handle,
00086         XtNlabel,       label,
00087         XtNalignment,   vert ? XfwfTop : XfwfLeft,
00088         XtNbackground,  wxGREY_PIXEL,
00089         XtNforeground,  wxBLACK_PIXEL,
00090         XtNhighlightColor, wxCTL_HIGHLIGHT_PIXEL,
00091         XtNfont,        font->GetInternalFont(),
00092 #ifdef WX_USE_XFT
00093         XtNxfont,       font->GetInternalAAFont(),
00094 #endif
00095         XtNshrinkToFit, TRUE,
00096         NULL);
00097     if (!(style & wxINVISIBLE))
00098       XtManageChild(wgt);
00099     else
00100       XtRealizeWidget(wgt);
00101     X->frame = wgt;
00102     // create widget
00103     wgt = XtVaCreateManagedWidget
00104        ("choice", xfwfLabelWidgetClass, X->frame,
00105         XtNlabel,       n > 0 ? choices[0] : "",
00106         XtNbackground,  wxBUTTON_PIXEL,
00107         XtNforeground,  wxBLACK_PIXEL,
00108         XtNfont,        font->GetInternalFont(),
00109 #ifdef WX_USE_XFT
00110         XtNxfont,       font->GetInternalAAFont(),
00111 #endif
00112         XtNframeWidth,  2,
00113         XtNhighlightThickness, 0,
00114         XtNalignment,   XfwfLeft,
00115         XtNrightMargin,  16,
00116         XtNshrinkToFit, (width < 0 || height < 0),
00117         // XtNtraversalOn, TRUE, /* MATTHEW */
00118         NULL);
00119     X->handle = wgt;
00120     // arrow widget which pops up a menu
00121     button = XtVaCreateManagedWidget
00122        ("choice_button", xfwfArrowWidgetClass, X->handle,
00123         XtNbackground,  wxBUTTON_PIXEL,
00124         XtNforeground,  wxBLACK_PIXEL,
00125         XtNdirection,   XfwfBottom,
00126         XtNrepeat,      FALSE,
00127         XtNarrowShadow, 0,
00128         XtNlocation,    "1.0 - 16 0.5 - 5 16 10",
00129         NULL);
00130     // set data declared in wxItem
00131     callback = function;
00132     XtAddCallback(button, XtNcallback, wxChoice::EventCallback, (XtPointer)saferef);
00133     X->extra = button;
00134 
00135     selection = n > 0 ? 0 : -1;
00136     for (int i = 0; i < n; ++i) {
00137       Append(choices[i]);
00138     }
00139 
00140     if (width < 0) {
00141       double maxw = 0, labelw = 0;
00142       for (int i = 0; i < n; i++) {
00143        double w, h;
00144        GetTextExtent(choices[i], &w, &h, NULL, NULL, font);
00145        if (w > maxw)
00146          maxw = w;
00147       }
00148       
00149       if (label && !vert) {
00150        double w, h;
00151        char *label_stripped;
00152        label_stripped = wxchoice_unprotect_amp(label);
00153        GetTextExtent(label_stripped, &w, &h, NULL, NULL, font);
00154        labelw = w + 2; /* 2 for separation btw label and ctl */
00155       }
00156 
00157       width = (int)(maxw + labelw + 32); /* 32 = space for arrow */
00158     }
00159 
00160     panel->PositionItem(this, x, y, width, height);
00161     AddEventHandlers();
00162 
00163     XtInsertEventHandler(button,
00164                       KeyPressMask |      // for PreOnChar
00165                       ButtonPressMask |   // for PreOnEvent
00166                       ButtonReleaseMask |
00167                       ButtonMotionMask |
00168                       PointerMotionMask | PointerMotionHintMask,
00169                       FALSE,
00170                       (XtEventHandler)wxWindow::WindowEventHandler,
00171                       (XtPointer)saferef,
00172                       XtListHead);
00173 
00174     XtInsertEventHandler(X->frame,
00175                       KeyPressMask, // for PreOnChar
00176                       FALSE,
00177                       (XtEventHandler)wxWindow::WindowEventHandler,
00178                       (XtPointer)saferef,
00179                       XtListHead);
00180 
00181     if (style & wxINVISIBLE)
00182       Show(FALSE);
00183 
00184     return TRUE;
00185 }
00186 
00187 wxChoice::~wxChoice (void)
00188 {
00189     if (choice_menu)
00190        DELETE_OBJ choice_menu;
00191     choice_menu = NULL;
00192     num_choices = 0;
00193 }
00194 
00195 //-----------------------------------------------------------------------------
00196 // size
00197 //-----------------------------------------------------------------------------
00198 
00199 void  wxChoice::GetSize(int *width, int *height)
00200 {
00201   wxWindow::GetSize(width, height);
00202 }
00203 
00204 
00205 //-----------------------------------------------------------------------------
00206 // methods to access internal data
00207 //-----------------------------------------------------------------------------
00208 
00209 static char *protect_amp(char *s)
00210 {
00211   if (strchr(s, '&')) {
00212     /* protect "&" */
00213     int i, amp = 0;
00214     char *s2;
00215     for (i = 0; s[i]; i++) {
00216       if (s[i] == '&')
00217        amp++;
00218     }
00219 
00220     s2 = new WXGC_ATOMIC char[i + amp + 1];
00221     for (i = 0, amp = 0; s[i]; i++, amp++) {
00222       s2[amp] = s[i];
00223       if (s[i] == '&') {
00224        s2[++amp] = '&';
00225       }
00226     }
00227     s2[amp] = 0;
00228     return s2;
00229   } else
00230     return s;
00231 }
00232 
00233 char *wxchoice_unprotect_amp(char *s)
00234 {
00235   if (strchr(s, '&')) {
00236     /* strip "&&" */
00237     int i, amp = 0;
00238     char *s2;
00239     for (i = 0; s[i]; i++) {
00240       if (s[i] == '&') {
00241        amp++;
00242        i++;
00243       }
00244     }
00245 
00246     s2 = new WXGC_ATOMIC char[i - amp + 1];
00247     amp = 0;
00248     for (i = 0; s[i]; i++, amp++) {
00249       if (s[i] == '&')
00250        i++;
00251       s2[amp] = s[i];
00252     }
00253     s2[amp] = 0;
00254     return s2;
00255   } else
00256     return s;
00257 }
00258 
00259 void wxChoice::Append(char *s)
00260 {
00261   s = protect_amp(s);
00262 
00263   choice_menu->Append(num_choices++, s, (char *)(-1));
00264   if (num_choices == 1) {
00265     XtVaSetValues(X->handle, XtNshrinkToFit, False, XtNlabel, s, NULL);
00266     selection = 0;
00267   }
00268 }
00269 
00270 void wxChoice::Clear(void)
00271 {
00272   wxMenu *naya;
00273   
00274   DELETE_OBJ choice_menu;
00275   naya = DEBUG_NEW wxMenu(NULL, (wxFunction)&(wxChoice::MenuEventCallback));
00276   choice_menu = naya;
00277   num_choices = 0;
00278   selection = 0;
00279   XtVaSetValues(X->handle, XtNshrinkToFit, False, XtNlabel, "", NULL);
00280 }
00281 
00282 int wxChoice::FindString(char *s)
00283 {
00284   s = protect_amp(s);
00285 
00286   return choice_menu->FindItem(s, 0);
00287 }
00288 
00289 char *wxChoice::GetString(int n)
00290 {
00291   char *s;
00292   s = choice_menu->GetLabel(n);
00293 
00294   return s ? wxchoice_unprotect_amp(s) : (char *)NULL;
00295 }
00296 
00297 char *wxChoice::GetStringSelection(void)
00298 {
00299   char *s;
00300   s = choice_menu->GetLabel(selection);
00301   
00302   return s ? wxchoice_unprotect_amp(s) : (char *)NULL;
00303 }
00304 
00305 void wxChoice::SetSelection(int n)
00306 {
00307   if (0 <= n && n < num_choices) {
00308     char *label;
00309     selection = n;
00310     label = choice_menu->GetLabel(n);
00311     XtVaSetValues(X->handle, XtNshrinkToFit, False, XtNlabel, label, NULL);
00312   }
00313 }
00314 
00315 Bool wxChoice::SetStringSelection(char *s)
00316 {
00317   int i;
00318   i = FindString(s);
00319   if (i > -1) {
00320     SetSelection(i);
00321     return TRUE;
00322   } else
00323     return FALSE;
00324 }
00325 
00326 void wxChoice::Command(wxCommandEvent *event)
00327 {
00328   ProcessCommand(event);
00329 }
00330 
00331 void wxChoice::ChangeToGray(Bool gray)
00332 {
00333   XtVaSetValues(X->extra, XtNdrawgrayArrow, (Boolean)gray, NULL);
00334   wxItem::ChangeToGray(gray);
00335 }
00336 
00337 //-----------------------------------------------------------------------------
00338 // callback for commandWidgetClass
00339 //-----------------------------------------------------------------------------
00340 
00341 void wxChoice::EventCallback(Widget WXUNUSED(w),
00342                           XtPointer clientData, XtPointer WXUNUSED(ptr))
00343 {
00344     wxChoice *choice = (wxChoice *)GET_SAFEREF(clientData);
00345     Dimension hh, ww;
00346 
00347     choice->SetFocus();
00348 
00349     choice->choice_menu->SetClientData(choice);
00350 
00351     // popup menu below "button"
00352     XtVaGetValues(choice->X->handle, XtNheight, &hh, XtNwidth, &ww, NULL);
00353 
00354     choice->choice_menu->SetWidth(ww);
00355 
00356     choice->PopupMenu(choice->choice_menu, 0, (int)hh - 2, TRUE, (int)hh);
00357 
00358 #ifdef MZ_PRECISE_GC
00359     XFORM_RESET_VAR_STACK;
00360 #endif
00361 }
00362 
00363 void wxChoice::OnEvent(wxMouseEvent *e)
00364 {
00365   if (e->ButtonDown())
00366     EventCallback(0, (XtPointer)saferef, 0);
00367 }
00368 
00369 void wxChoice::MenuEventCallback(wxObject* obj, wxCommandEvent* ev)
00370 {
00371     wxChoice       *choice;
00372     wxPopupEvent *pu = (wxPopupEvent *)ev;
00373     wxCommandEvent *event;
00374 
00375     choice = (wxChoice*)((wxMenu *)obj)->GetClientData();
00376 
00377     if (!choice->Number())
00378       return;
00379 
00380     event = new wxCommandEvent(wxEVENT_TYPE_CHOICE_COMMAND);
00381 
00382     choice->SetSelection(pu->menuId);
00383     choice->ProcessCommand(event);
00384 }
00385 
00386 void wxChoice::OnChar(wxKeyEvent *e)
00387 {
00388   int delta = 0;
00389 
00390   switch (e->keyCode) {
00391   case WXK_UP:
00392     delta = -1;
00393     break;
00394   case WXK_DOWN:
00395     delta = 1;
00396     break;
00397   }
00398 
00399   if (delta) {
00400     int s;
00401     s = GetSelection();
00402     SetSelection(s + delta);
00403     if (s != GetSelection()) {
00404       wxCommandEvent *event;
00405       event = new wxCommandEvent(wxEVENT_TYPE_CHOICE_COMMAND);
00406       ProcessCommand(event);
00407     }
00408   }
00409 }