Back to index

plt-scheme  4.2.1
RadioBox.cc
Go to the documentation of this file.
00001 /*                                                      -*- C++ -*-
00002  *
00003  * Purpose: radio box 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 "RadioBox.h"
00029 #endif
00030 
00031 #define  Uses_XtIntrinsic
00032 #define  Uses_wxRadioBox
00033 #define  Uses_wxTypeTree
00034 #include "wx.h"
00035 #define  Uses_EnforcerWidget
00036 #define  Uses_GroupWidget
00037 #define  Uses_ToggleWidget
00038 #include "widgets.h"
00039 
00040 #define TOGGLES ((Widget*)toggles)
00041 
00042 //-----------------------------------------------------------------------------
00043 // create and destroy button
00044 //-----------------------------------------------------------------------------
00045 
00046 wxRadioBox::wxRadioBox(wxPanel *panel, wxFunction func, char *label,
00047                      int x, int y, int width, int height, int n, char **choices,
00048                      int num_rows, long style, wxFont *_font, char *name) : wxItem(_font)
00049 {
00050     __type = wxTYPE_RADIO_BOX;
00051 
00052     toggles     = NULL;
00053     num_toggles = 0;
00054 
00055     Create(panel, func, label, x, y, width, height, n, choices,
00056           num_rows, style, name);
00057 }
00058 
00059 wxRadioBox::wxRadioBox(wxPanel *panel, wxFunction func, char *label,
00060                      int x, int y, int width, int height, int n, wxBitmap **choices,
00061                      int num_rows, long style, wxFont *_font, char *name) : wxItem(_font)
00062 {
00063     __type = wxTYPE_RADIO_BOX;
00064 
00065     toggles     = NULL;
00066     num_toggles = 0;
00067 
00068     Create(panel, func, label, x, y, width, height, n, choices,
00069           num_rows, style, name);
00070 }
00071 
00072 Bool wxRadioBox::Create(wxPanel *panel, wxFunction func, char *label,
00073                  int x, int y, int width, int height, int n, char **choices,
00074                  int num_rows, long style, char *name)
00075 {
00076     int i;
00077     wxWindow_Xintern *ph;
00078     Bool vert;
00079     Dimension ww, hh;
00080     double lw, lh;
00081     Widget wgt;
00082 
00083     if ( (num_toggles = n) <= 0 ) {
00084        wxDebugMsg("%s created without items (n=0)!\n", name);
00085        return TRUE;
00086     }
00087 
00088     bm_labels = NULL;
00089     bm_label_masks = NULL;
00090 
00091     ChainToPanel(panel, style, name);
00092 
00093     if (style & wxVERTICAL_LABEL)
00094       vert = 1;
00095     else if (style & wxHORIZONTAL_LABEL)
00096       vert = 0;
00097     else
00098       vert = (panel->GetLabelPosition() == wxVERTICAL);
00099 
00100     label = wxGetCtlLabel(label);
00101 
00102     if ((style & wxVERTICAL) == wxVERTICAL) {
00103       if (num_rows <= 0)
00104        num_rows = num_toggles;
00105       else
00106        num_rows = 1;
00107     } else {
00108       if (num_rows <= 0)
00109        num_rows = 1;
00110       else
00111        num_rows = num_toggles / num_rows;
00112     }
00113 
00114     ph = parent->GetHandle();
00115     
00116     // create frame
00117     wgt = XtVaCreateWidget(name, xfwfEnforcerWidgetClass, ph->handle,
00118                         XtNlabel,       label,
00119                         XtNalignment,   vert ? XfwfTop : XfwfLeft,
00120                         XtNbackground,  wxGREY_PIXEL,
00121                         XtNforeground,  wxBLACK_PIXEL,
00122                         XtNfont,        font->GetInternalFont(),
00123 #ifdef WX_USE_XFT
00124                         XtNxfont,       font->GetInternalAAFont(),
00125 #endif
00126                         XtNframeType,   (style & wxFLAT) ? XfwfChiseled : XfwfSunken,
00127                         XtNframeWidth,  0,
00128                         XtNshrinkToFit, (width < 0 || height < 0),
00129                         NULL);
00130     if (!(style & wxINVISIBLE))
00131       XtManageChild(wgt);
00132     else
00133       XtRealizeWidget(wgt);
00134     X->frame = wgt;
00135     // create group widget, which holds the toggles
00136     wgt = XtVaCreateManagedWidget("radiobox", xfwfGroupWidgetClass, X->frame,
00137                               XtNselectionStyle, (style & wxAT_MOST_ONE) ?
00138                               XfwfSingleSelection : XfwfOneSelection,
00139                               XtNstoreByRow,     FALSE,
00140                               XtNlabel,          NULL,
00141                               XtNframeWidth,     0,
00142                               XtNbackground,     wxGREY_PIXEL,
00143                               XtNrows,           num_rows,
00144                               XtNshrinkToFit,    (width < 0 || height < 0),
00145                               NULL);
00146     X->handle = wgt;
00147     // create the toggles
00148     toggles = new WXGC_ATOMIC long[num_toggles];
00149     enabled = new WXGC_ATOMIC Bool[num_toggles];
00150     for (i=0; i < num_toggles; ++i) {
00151        char num_name[10]; 
00152        char *tlabel;
00153         enabled[i] = 1;
00154        sprintf(num_name, "%d", i);
00155        tlabel = wxGetCtlLabel(choices[i]);
00156        wgt = XtVaCreateManagedWidget(num_name, xfwfToggleWidgetClass, X->handle,
00157                                   XtNlabel,         tlabel,
00158                                   XtNbackground,    wxGREY_PIXEL,
00159                                   XtNforeground,    wxBLACK_PIXEL,
00160                                   XtNhighlightColor, wxCTL_HIGHLIGHT_PIXEL,
00161                                   XtNfont,          font->GetInternalFont(),
00162 #ifdef WX_USE_XFT
00163                                   XtNxfont,         font->GetInternalAAFont(),
00164 #endif
00165                                   XtNshrinkToFit,   TRUE,
00166                                   NULL);
00167        ((Widget*)toggles)[i] = wgt;
00168     }
00169     // set data declared in wxItem
00170     callback = func;
00171     XtAddCallback(X->handle, XtNactivate, wxRadioBox::EventCallback,
00172                 (XtPointer)saferef);
00173     // resize enforcer
00174     XtVaGetValues(X->handle, XtNwidth, &ww, XtNheight, &hh, NULL);
00175     if (label)
00176       GetTextExtent(label, &lw, &lh, NULL, NULL, font);
00177     else {
00178       lw = lh = 0;
00179     }
00180     if (vert) hh += int(lh);
00181     else      ww += int(lw);
00182     XtVaSetValues(X->frame, XtNwidth, ww+4, XtNheight, hh+4, NULL);
00183     // panel positioning
00184     panel->PositionItem(this, x, y, width, height);
00185     AddEventHandlers();
00186 
00187     for (i = 0; i < num_toggles; i++) {
00188       XtInsertEventHandler(((Widget*)toggles)[i],
00189                         KeyPressMask |    // for PreOnChar
00190                         ButtonPressMask | // for PreOnEvent
00191                         ButtonReleaseMask |
00192                         ButtonMotionMask |
00193                         PointerMotionMask | PointerMotionHintMask,
00194                         FALSE,
00195                         (XtEventHandler)wxWindow::WindowEventHandler,
00196                         (XtPointer)saferef,
00197                         XtListHead);
00198     }
00199 
00200     if (style & wxINVISIBLE)
00201       Show(FALSE);
00202 
00203     return TRUE;
00204 }
00205 
00206 Bool wxRadioBox::Create(wxPanel *panel, wxFunction func, char *label,
00207                  int x, int y, int width, int height, int n, wxBitmap **choices,
00208                  int num_rows, long style, char *name)
00209 {
00210     int i;
00211     Bool vert;
00212     wxWindow_Xintern *ph;
00213     Dimension ww, hh; double lw, lh;
00214     Widget wgt;
00215 
00216     if ( (num_toggles = n) <= 0 ) {
00217        wxDebugMsg("%s created without items (n=0)!\n", name);
00218        return TRUE;
00219     }
00220 
00221     ChainToPanel(panel, style, name);
00222 
00223     label = wxGetCtlLabel(label);
00224 
00225     if (style & wxVERTICAL_LABEL)
00226       vert = 1;
00227     else if (style & wxHORIZONTAL_LABEL)
00228       vert = 0;
00229     else
00230       vert = (panel->GetLabelPosition() == wxVERTICAL);
00231     
00232     if ((style & wxVERTICAL) == wxVERTICAL) {
00233       if (num_rows <= 0)
00234        num_rows = num_toggles;
00235       else
00236        num_rows = 1;
00237     } else {
00238       if (num_rows <= 0)
00239        num_rows = 1;
00240       else
00241        num_rows = num_toggles / num_rows;
00242     }
00243 
00244     ph = parent->GetHandle();
00245 
00246     // create frame
00247     wgt = XtVaCreateWidget(name, xfwfEnforcerWidgetClass, ph->handle,
00248                         XtNlabel,       label,
00249                         XtNalignment,   vert ? XfwfTop : XfwfLeft,
00250                         XtNbackground,  wxGREY_PIXEL,
00251                         XtNforeground,  wxBLACK_PIXEL,
00252                         XtNfont,        font->GetInternalFont(),
00253 #ifdef WX_USE_XFT
00254                         XtNxfont,       font->GetInternalAAFont(),
00255 #endif
00256                         XtNframeType,   (style & wxFLAT) ? XfwfChiseled : XfwfSunken,
00257                         XtNframeWidth,  0,
00258                         XtNshrinkToFit, TRUE,
00259                         NULL);
00260     if (!(style & wxINVISIBLE))
00261       XtManageChild(wgt);
00262     else
00263       XtRealizeWidget(wgt);
00264     X->frame = wgt;
00265 
00266     // create group widget, which holds the toggles
00267     wgt = XtVaCreateManagedWidget("radiobox", xfwfGroupWidgetClass, X->frame,
00268                               XtNselectionStyle, (style & wxAT_MOST_ONE) ?
00269                               XfwfSingleSelection : XfwfOneSelection,
00270                               XtNstoreByRow,     FALSE,
00271                               XtNlabel,          NULL,
00272                               XtNframeWidth,     0,
00273                               XtNbackground,     wxGREY_PIXEL,
00274                               XtNrows,           num_rows,
00275                               XtNshrinkToFit,    TRUE,
00276                               NULL);
00277     X->handle = wgt;
00278     // create the toggles
00279     toggles = new WXGC_ATOMIC long[num_toggles];
00280     enabled = new WXGC_ATOMIC Bool[num_toggles];
00281 #ifdef MZ_PRECISE_GC
00282     {
00283       wxBitmap **ba;
00284       ba = (wxBitmap **)GC_malloc(num_toggles * sizeof(wxBitmap *));
00285       bm_labels = ba;
00286       ba = (wxBitmap **)GC_malloc(num_toggles * sizeof(wxBitmap *));
00287       bm_label_masks = ba;
00288     }
00289 #else
00290     bm_labels = new WXGC_PTRS wxBitmap*[num_toggles];
00291     bm_label_masks = new WXGC_PTRS wxBitmap*[num_toggles];
00292 #endif
00293     for (i=0; i < num_toggles; ++i) {
00294        char num_name[10];
00295        char *kind;
00296        void *label;
00297        wxBitmap *achoice;
00298        void *mpm;
00299 
00300        sprintf(num_name, "%d", i);
00301 
00302        enabled[i] = 1;
00303 
00304        achoice = choices[i];
00305        if (achoice->Ok() && (achoice->selectedIntoDC >= 0)) {
00306          kind = XtNpixmap;
00307          label = achoice->GetLabelPixmap();
00308          bm_labels[i] = achoice;
00309          achoice->selectedIntoDC++;
00310          achoice = CheckMask(bm_labels[i]);
00311          bm_label_masks[i] = achoice;
00312          if (achoice)
00313            mpm = (void *)GETPIXMAP(achoice);
00314          else
00315            mpm = NULL;
00316        } else {
00317          kind = XtNlabel;
00318          label = (char *)"<bad-image>";
00319          bm_labels[i] = NULL;
00320          bm_label_masks[i] = NULL;
00321          mpm = NULL;
00322        }
00323 
00324        wgt = XtVaCreateManagedWidget(num_name, xfwfToggleWidgetClass, X->handle,
00325                                   kind,             label,
00326                                   XtNmaskmap,       mpm,
00327                                   XtNbackground,    wxGREY_PIXEL,
00328                                   XtNforeground,    wxBLACK_PIXEL,
00329                                   XtNhighlightColor, wxCTL_HIGHLIGHT_PIXEL,
00330                                   XtNfont,          font->GetInternalFont(),
00331 #ifdef WX_USE_XFT
00332                                   XtNxfont,         font->GetInternalAAFont(),
00333 #endif
00334                                   XtNshrinkToFit,   TRUE,
00335                                   NULL);
00336        ((Widget*)toggles)[i] = wgt;
00337     }
00338     // set data declared in wxItem
00339     callback = func;
00340     XtAddCallback(X->handle, XtNactivate, wxRadioBox::EventCallback,
00341                 (XtPointer)saferef);
00342     // resize enforcer
00343     XtVaGetValues(X->handle, XtNwidth, &ww, XtNheight, &hh, NULL);
00344     if (label)
00345       GetTextExtent(label, &lw, &lh, NULL, NULL, font);
00346     else {
00347       lw = lh = 0;
00348     }
00349     if (vert) hh += int(lh);
00350     else      ww += int(lw);
00351     XtVaSetValues(X->frame, XtNwidth, ww+4, XtNheight, hh+4, NULL);
00352     // panel positioning
00353     panel->PositionItem(this, x, y, width, height);
00354     AddEventHandlers();
00355 
00356     for (i = 0; i < num_toggles; i++) {
00357       XtInsertEventHandler(((Widget*)toggles)[i],
00358                         KeyPressMask |    // for PreOnChar
00359                         ButtonPressMask | // for PreOnEvent
00360                         ButtonReleaseMask |
00361                         ButtonMotionMask |
00362                         PointerMotionMask | PointerMotionHintMask,
00363                         FALSE,
00364                         (XtEventHandler)wxWindow::WindowEventHandler,
00365                         (XtPointer)saferef,
00366                         XtListHead);
00367     }
00368 
00369     if (style & wxINVISIBLE)
00370       Show(FALSE);
00371 
00372     return TRUE;
00373 }
00374 
00375 wxRadioBox::~wxRadioBox(void)
00376 {
00377   if (bm_labels) {
00378     int i;
00379     for (i = 0; i < num_toggles; i++) {
00380       if (bm_labels[i]) {
00381        wxBitmap *bm = bm_labels[i];
00382        --bm->selectedIntoDC;
00383        bm->ReleaseLabel();
00384        XtVaSetValues(((Widget*)toggles)[i], 
00385                     XtNpixmap, NULL, 
00386                     XtNmaskmap, NULL, 
00387                     NULL);
00388       }
00389       if (bm_label_masks[i]) {
00390        wxBitmap *bm = bm_label_masks[i];
00391        --bm->selectedIntoDC;
00392       }
00393     }
00394     bm_labels = NULL;
00395     bm_label_masks = NULL;
00396   }
00397 }
00398 
00399 //-----------------------------------------------------------------------------
00400 // methods to access internal data
00401 //-----------------------------------------------------------------------------
00402 
00403 void wxRadioBox::Enable(int item, Bool enable)
00404 {
00405   if (0 <= item && item < num_toggles) {
00406     enabled[item] = enable;
00407     if (!IsGray())
00408       XtSetSensitive(TOGGLES[item], enable);
00409   }
00410 }
00411 
00412 void wxRadioBox::ChangeToGray(Bool gray)
00413 {
00414   int i;
00415 
00416   wxWindow::ChangeToGray(gray);
00417   for (i = 0; i < num_toggles; i++) {
00418     XtSetSensitive(TOGGLES[i], gray ? FALSE : enabled[i]);
00419   }
00420 }
00421 
00422 int wxRadioBox::FindString(char *s)
00423 {
00424   int i;
00425   for (i = 0; i < num_toggles; i++) {
00426     char *l;
00427     l = GetLabel(i);
00428     if (l && !strcmp(l, s))
00429       return i;
00430   }
00431   return -1;
00432 }
00433 
00434 char *wxRadioBox::GetLabel(int item)
00435 {
00436     char *label = NULL;
00437 
00438     if (0 <= item && item < num_toggles)
00439        XtVaGetValues(TOGGLES[item], XtNlabel, &label, NULL);
00440 
00441     return label;
00442 }
00443 
00444 int wxRadioBox::GetSelection(void)
00445 {
00446     long selection;
00447 
00448     if (!num_toggles)
00449       return -1;
00450 
00451     XtVaGetValues(X->handle, XtNselection, &selection, NULL);
00452 
00453     return int(selection);
00454 }
00455 
00456 char *wxRadioBox::GetStringSelection(void)
00457 {
00458     char *label = NULL;
00459     int  item;
00460     item = GetSelection();
00461 
00462     if (0 <= item && item < num_toggles)
00463        XtVaGetValues(TOGGLES[item], XtNlabel, &label, NULL);
00464     return label;
00465 }
00466 
00467 char *wxRadioBox::GetString(int which)
00468 {
00469     char *label = NULL;
00470 
00471     if (0 <= which && which < num_toggles)
00472        XtVaGetValues(TOGGLES[which], XtNlabel, &label, NULL);
00473     return label;
00474 }
00475 
00476 void wxRadioBox::SetLabel(int item, char *label)
00477 {
00478   label = wxGetCtlLabel(label);
00479 
00480   if (0 <= item && item < num_toggles
00481       && (!bm_labels || !bm_labels[item]))
00482     XtVaSetValues(TOGGLES[item], XtNlabel, label, NULL);
00483 }
00484 
00485 void wxRadioBox::SetLabel(int item, wxBitmap *bitmap)
00486 {
00487   if (0 <= item && item < num_toggles
00488       && bm_labels && bm_labels[item]) {
00489     Pixmap pm, mpm;
00490     wxBitmap *obm;
00491 
00492     obm = bm_labels[item];
00493     --obm->selectedIntoDC;
00494     obm->ReleaseLabel();
00495     obm = bm_label_masks[item];
00496     if (obm)
00497       --obm->selectedIntoDC;
00498 
00499     bm_labels[item] = bitmap;
00500     bitmap->selectedIntoDC++;
00501 
00502     obm = CheckMask(bitmap);
00503     bm_label_masks[item] = obm;
00504 
00505     pm = (Pixmap)bitmap->GetLabelPixmap();
00506     if (obm)
00507       mpm = GETPIXMAP(obm);
00508     else
00509       mpm = 0;
00510 
00511     XtVaSetValues(TOGGLES[item], 
00512                 XtNlabel, NULL,
00513                 XtNpixmap, pm, 
00514                 XtNmaskmap, mpm, 
00515                 NULL);
00516   }
00517 }
00518 
00519 void wxRadioBox::SetSelection(int item)
00520 {
00521   if (0 <= item && item < num_toggles)
00522     XtVaSetValues(X->handle, XtNselection, (long)item, NULL);
00523 }
00524 
00525 void wxRadioBox::SetStringSelection(char *s)
00526 {
00527   SetSelection(FindString(s));
00528 }
00529 
00530 Bool wxRadioBox::Show(int item, Bool show)
00531 {
00532   if (0 <= item && item < num_toggles) {
00533     if (show) XtMapWidget(TOGGLES[item]);
00534     else      XtUnmapWidget(TOGGLES[item]);
00535   }
00536   return FALSE;
00537 }
00538 
00539 void wxRadioBox::Command(wxCommandEvent *event)
00540 {
00541   ProcessCommand(event);
00542 }
00543 
00544 //-----------------------------------------------------------------------------
00545 // callbacks for xfwfGroupWidgetClass
00546 //-----------------------------------------------------------------------------
00547 
00548 void wxRadioBox::SetSelectedButtonFocus()
00549 {
00550   ButtonFocus(GetSelection());
00551 }
00552 
00553 void wxRadioBox::EventCallback(Widget WXUNUSED(w), XtPointer dclient, XtPointer WXUNUSED(dcall))
00554 {
00555     wxRadioBox     *radioBox = (wxRadioBox *)GET_SAFEREF(dclient);
00556     wxCommandEvent *event;
00557 
00558     event = new wxCommandEvent(wxEVENT_TYPE_RADIOBOX_COMMAND);
00559 
00560     radioBox->SetSelectedButtonFocus();
00561 
00562     radioBox->ProcessCommand(event);
00563 
00564 #ifdef MZ_PRECISE_GC
00565     XFORM_RESET_VAR_STACK;
00566 #endif
00567 }
00568 
00569 extern "C" Boolean has_focus_now(Widget w);
00570 
00571 int wxRadioBox::ButtonFocus(int which)
00572 {
00573   if (which > num_toggles) return -1;
00574 
00575   if (which > -1) {
00576     // Set the focus on the just-clicked button
00577     // find frame of this widget
00578     wxWindow *win = this;
00579     for (/*wxWindow *win = this*/; win; win = win->GetParent()) {
00580       if (wxSubType(win->__type, wxTYPE_FRAME))
00581        break;
00582     }
00583     
00584     if (win) {
00585       wxWindow_Xintern *h;
00586       h = win->GetHandle();
00587       XtSetKeyboardFocus(h->frame, (Widget)TOGGLES[which]);
00588     }
00589 
00590     return -1;
00591   } else {
00592     int i;
00593     for (i = num_toggles; i--; ) {
00594       Widget w = (Widget)TOGGLES[i];
00595       if (has_focus_now(w))
00596        return i;
00597     }
00598     return -1;
00599   }
00600 }