/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ /* Button.cpp -- implementation file for XFE_Button. Created: Chris McAfee , Wed Nov 6 11:11:42 PST 1996 */ #include "Button.h" #include "Command.h" #include "mozilla.h" #include "icons.h" #include "prefapi.h" #include #include #include #include #include #include "xpgetstr.h" // for XP_GetString() extern int XFE_UNTITLED; const char * XFE_Button::doCommandCallback = "XFE_Button::doCommandCallback"; #if defined(DEBUG_tao_) #define XDBG(x) x #else #define XDBG(x) #endif void XFE_Button::tip_cb(Widget w, XtPointer clientData, XtPointer cb_data) { XFE_Button *obj = (XFE_Button *) clientData; obj->tipCB(w, cb_data); } void XFE_Button::tipCB(Widget /* w */, XtPointer cb_data) { XFE_TipStringCallbackStruct* cbs = (XFE_TipStringCallbackStruct*)cb_data; /* get frame first */ XFE_Frame * frame = (XFE_Frame *) getToplevel(); if (!frame) { return; }/* if */ XDBG(printf("\n *** XFE_Button::tipCB: parent Frame found for %s! *** \n", XtName(w))); char *rtn = 0; if (cbs->reason == XFE_DOCSTRING) { rtn = frame->getDocString(m_cmd); } else if (cbs->reason == XFE_TIPSTRING) { rtn = frame->getTipString(m_cmd); } if (rtn) { *cbs->string = rtn; } } // Can't just pass in a XFE_Frame, we might be in a XFE_Dialog. // Cast to XFE_Component superclass. ////////////////////////////////////////////////////////////////////////// XFE_Button::XFE_Button(XFE_Frame * frame, Widget parent, const char * name, IconGroup * iconGroup, IconGroup * iconGroup2, IconGroup * iconGroup3, IconGroup * iconGroup4) : XFE_Component(frame) { XP_ASSERT(parent); XP_ASSERT(frame); m_icons[0] = iconGroup; m_icons[1] = iconGroup2; m_icons[2] = iconGroup3; m_icons[3] = iconGroup4; m_currentIconGroup = 0; m_name = name ? name : XP_GetString(XFE_UNTITLED); m_cmd = Command::intern((char *) m_name); m_callData = NULL; m_widget = createButton(parent,xfeButtonWidgetClass); installDestroyHandler(); // Set the new pixmap group if needed if (m_icons[m_currentIconGroup]) { setPixmap(m_icons[m_currentIconGroup]); } } ////////////////////////////////////////////////////////////////////////// XFE_Button::XFE_Button(XFE_Frame * frame, Widget parent, const char * name, MenuSpec * spec, IconGroup * iconGroup, IconGroup * iconGroup2, IconGroup * iconGroup3, IconGroup * iconGroup4) : XFE_Component(frame) { XP_ASSERT(parent); XP_ASSERT(frame); m_icons[0] = iconGroup; m_icons[1] = iconGroup2; m_icons[2] = iconGroup3; m_icons[3] = iconGroup4; m_currentIconGroup = 0; m_name = name ? name : XP_GetString(XFE_UNTITLED); m_cmd = Command::intern((char *) m_name); m_callData = NULL; m_widget = createButton(parent,xfeCascadeWidgetClass); installDestroyHandler(); // Set the new pixmap group if needed if (m_icons[m_currentIconGroup]) { setPixmap(m_icons[m_currentIconGroup]); } setMenuSpec(spec); } ////////////////////////////////////////////////////////////////////////// XFE_Button::XFE_Button(XFE_Frame * frame, Widget parent, const char * name, dynamenuCreateProc generateProc, void * generateArg, IconGroup * iconGroup, IconGroup * iconGroup2, IconGroup * iconGroup3, IconGroup * iconGroup4) : XFE_Component(frame) { XP_ASSERT(parent); XP_ASSERT(frame); m_icons[0] = iconGroup; m_icons[1] = iconGroup2; m_icons[2] = iconGroup3; m_icons[3] = iconGroup4; m_currentIconGroup = 0; m_name = name ? name : XP_GetString(XFE_UNTITLED); m_cmd = Command::intern((char *) m_name); m_callData = NULL; m_widget = createButton(parent,xfeCascadeWidgetClass); installDestroyHandler(); // Set the new pixmap group if needed if (m_icons[m_currentIconGroup]) { setPixmap(m_icons[m_currentIconGroup]); } (*generateProc)(m_widget,generateArg,frame); } ////////////////////////////////////////////////////////////////////////// XFE_Button::~XFE_Button() { } ////////////////////////////////////////////////////////////////////////// void XFE_Button::setPixmap(IconGroup * icons) { fe_buttonSetPixmaps(m_widget,icons); } ////////////////////////////////////////////////////////////////////////// void XFE_Button::setLabel(char *label) { XfeSetXmStringPSZ(m_widget, XmNlabelString, XmFONTLIST_DEFAULT_TAG, label); } ////////////////////////////////////////////////////////////////////////// Widget XFE_Button::createButton(Widget parent,WidgetClass wc) { XP_ASSERT( XfeIsAlive(parent) ); XP_ASSERT( (wc == xfeButtonWidgetClass) || (wc == xfeCascadeWidgetClass) ); Widget button; button = XtVaCreateWidget(m_name,wc,parent, XmNinstancePointer, this, NULL); XtAddCallback(button, XmNactivateCallback, &XFE_Button::activate_cb, (XtPointer) this); /* Add tooltip to button */ #if 1 fe_AddTipStringCallback(button, XFE_Button::tip_cb, this); #else // Add tooltip to button fe_WidgetAddToolTips(button); #endif return button; } ////////////////////////////////////////////////////////////////////////// void XFE_Button::activate_cb(Widget w, XtPointer clientData, XtPointer callData) { XFE_Button * button = (XFE_Button*) clientData; XfeButtonCallbackStruct * cd = (XfeButtonCallbackStruct *) callData; CommandType cmd = button->getCmd(); void * cmdCallData = button->getCallData(); // The command info - only widget and event available XFE_CommandInfo info(XFE_COMMAND_BUTTON_ACTIVATE,w,cd->event); // Command arguments XFE_DoCommandArgs cmdArgs(cmd,cmdCallData,&info); // Send a message that will perform an action. button->notifyInterested(XFE_Button::doCommandCallback,(void *) &cmdArgs); } ////////////////////////////////////////////////////////////////////////// void XFE_Button::sub_menu_cb(Widget w, XtPointer clientData, XtPointer callData) { XFE_Button * obj = (XFE_Button*) clientData; XmAnyCallbackStruct * cbs = (XmAnyCallbackStruct *) callData; CommandType cmd = Command::intern(XtName(w)); XP_ASSERT( obj != NULL ); if (!obj) { return; } XFE_Frame * frame = (XFE_Frame *) obj->getToplevel(); XP_ASSERT( frame != NULL ); if (!frame) { return; } switch(cbs->reason) { case XmCR_ARM: frame->notifyInterested(Command::commandArmedCallback,(void*) cmd); break; case XmCR_DISARM: frame->notifyInterested(Command::commandDisarmedCallback,(void*)cmd); break; case XmCR_ACTIVATE: { XFE_CommandInfo e_info(XFE_COMMAND_BUTTON_ACTIVATE, w,cbs->event,NULL,0); MenuSpec * spec = (MenuSpec *) XfeUserData(w); if ( spec && spec->tag == CUSTOMBUTTON ) { cmd = spec->getCmdName(); if (frame->handlesCommand(cmd) && frame->isCommandEnabled(cmd)) { xfe_ExecuteCommand(frame, cmd, spec->callData, &e_info); } } else { if (frame->handlesCommand(cmd) && frame->isCommandEnabled(cmd)) { xfe_ExecuteCommand(frame, cmd, NULL, &e_info); } } } break; case XmCR_VALUE_CHANGED: { XFE_CommandInfo e_info(XFE_COMMAND_BUTTON_ACTIVATE, w,cbs->event,NULL,0); // if (frame->handlesCommand(cmd) && frame->isCommandSelected(cmd)) if (frame->handlesCommand(cmd)) { xfe_ExecuteCommand(frame, cmd, NULL, &e_info); } } break; } } ////////////////////////////////////////////////////////////////////////// void XFE_Button::setMenuSpec(MenuSpec * spec) { XP_ASSERT( XfeIsAlive(m_widget) ); XP_ASSERT( XfeIsCascade(m_widget) ); Widget sub_menu_id; MenuSpec * cur_spec; XtVaGetValues(m_widget,XmNsubMenuId,&sub_menu_id,NULL); XP_ASSERT( XfeIsAlive(sub_menu_id) ); // Make sure a menu spec is given if (!spec) { return; } cur_spec = spec; // Create toolbar buttons while (cur_spec->menuItemName) { switch(cur_spec->tag) { case PUSHBUTTON: { Widget pb=XtVaCreateManagedWidget(cur_spec->menuItemName, xmPushButtonGadgetClass, sub_menu_id, XmNuserData, cur_spec, NULL); XtAddCallback(pb, XmNactivateCallback, XFE_Button::sub_menu_cb, (XtPointer) this); XtAddCallback(pb, XmNarmCallback, XFE_Button::sub_menu_cb, (XtPointer) this); XtAddCallback(pb, XmNdisarmCallback, XFE_Button::sub_menu_cb, (XtPointer) this); } break; case CUSTOMBUTTON: { char* str; XmString xm_str; KeySym mnemonic; if ( !PREF_GetLabelAndMnemonic((char*) cur_spec->callData, &str, &xm_str, &mnemonic) ) break; if ( !strcmp(str, "-") ) { XtVaCreateManagedWidget(spec->menuItemName, xmSeparatorGadgetClass, sub_menu_id, XmNshadowThickness, 2, NULL); } else { Widget pb=XtVaCreateManagedWidget(cur_spec->menuItemName, xmPushButtonGadgetClass, sub_menu_id, XmNuserData, cur_spec, XmNlabelString, xm_str, mnemonic ? XmNmnemonic : NULL, mnemonic, NULL); XtAddCallback(pb, XmNactivateCallback, XFE_Button::sub_menu_cb, (XtPointer) this); XtAddCallback(pb, XmNarmCallback, XFE_Button::sub_menu_cb, (XtPointer) this); XtAddCallback(pb, XmNdisarmCallback, XFE_Button::sub_menu_cb, (XtPointer) this); } XmStringFree(xm_str); } break; case TOGGLEBUTTON: { Widget tb=XtVaCreateManagedWidget(cur_spec->menuItemName, xmToggleButtonGadgetClass, sub_menu_id, XmNuserData, cur_spec, NULL); XtAddCallback(tb, XmNvalueChangedCallback, XFE_Button::sub_menu_cb, (XtPointer) this); XtAddCallback(tb, XmNarmCallback, XFE_Button::sub_menu_cb, (XtPointer) this); XtAddCallback(tb, XmNdisarmCallback, XFE_Button::sub_menu_cb, (XtPointer) this); } break; case SEPARATOR: XtVaCreateManagedWidget(spec->menuItemName, xmSeparatorGadgetClass, sub_menu_id, XmNshadowThickness, 2, NULL); break; case DYNA_MENUITEMS: XP_ASSERT( cur_spec != NULL ); XP_ASSERT( cur_spec->generateProc != NULL ); (*cur_spec->generateProc)(m_widget, cur_spec->callData, (XFE_Frame *) m_toplevel); break; case DYNA_CASCADEBUTTON: case DYNA_FANCY_CASCADEBUTTON: { XP_ASSERT( cur_spec != NULL ); XP_ASSERT( cur_spec->generateProc != NULL ); Widget top_level = m_toplevel->getBaseWidget(); Visual * visual = XfeVisual(top_level); Colormap cmap = XfeColormap(top_level); Cardinal depth = XfeDepth(top_level); Arg av[10]; Cardinal ac = 0; Widget pulldown; Widget cascade; WidgetClass wc = NULL; ac = 0; XtSetArg(av[ac],XmNvisual, visual); ac++; XtSetArg(av[ac],XmNcolormap, cmap); ac++; XtSetArg(av[ac],XmNdepth, depth); ac++; pulldown = XmCreatePulldownMenu(sub_menu_id,"pulldown",av,ac); if (cur_spec->tag == DYNA_FANCY_CASCADEBUTTON) { wc = xfeBmCascadeWidgetClass; } else { wc = xmCascadeButtonWidgetClass; } cascade = XtVaCreateManagedWidget(cur_spec->menuItemName, wc, sub_menu_id, XmNsubMenuId, pulldown, NULL); (*cur_spec->generateProc)(cascade, cur_spec->callData, (XFE_Frame *) m_toplevel); } break; default: XP_ASSERT(0); break; } cur_spec++; } } ////////////////////////////////////////////////////////////////////////// int XFE_Button::getIconGroupIndex() { return m_currentIconGroup; } ////////////////////////////////////////////////////////////////////////// void XFE_Button::setIconGroups (IconGroup *iconGroup, IconGroup *iconGroup2, IconGroup *iconGroup3, IconGroup *iconGroup4) { m_icons[0] = iconGroup; m_icons[1] = iconGroup2; m_icons[2] = iconGroup3; m_icons[3] = iconGroup4; if (m_icons[m_currentIconGroup] == NULL) m_currentIconGroup = 0; } ////////////////////////////////////////////////////////////////////////// void XFE_Button::useIconGroup (int iconGroupIndex) { if (m_currentIconGroup != iconGroupIndex && iconGroupIndex >= 0 && iconGroupIndex < MAX_ICON_GROUPS && m_icons[iconGroupIndex] != NULL) { setPixmap(m_icons[iconGroupIndex]); m_currentIconGroup = iconGroupIndex; } } ////////////////////////////////////////////////////////////////////////// void XFE_Button::setPretendSensitive(Boolean state) { XP_ASSERT( XfeIsAlive(m_widget) ); XfeSetPretendSensitive(m_widget,state); } ////////////////////////////////////////////////////////////////////////// Boolean XFE_Button::isPretendSensitive() { XP_ASSERT( XfeIsAlive(m_widget) ); return XfeIsPretendSensitive(m_widget); } ////////////////////////////////////////////////////////////////////////// void XFE_Button::setPopupDelay(int delay) { XP_ASSERT( XfeIsAlive(m_widget) ); XP_ASSERT( XfeIsCascade(m_widget) ); XtVaSetValues(m_widget,XmNmappingDelay,delay,NULL); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // fe_buttonSetPixmaps() // // This function should be used to configure the icons of any widget that // is a XfeButton (or subclass). // // Only the normal pixmap/mask (XmNpixmap,XmNpixmapMask) and the mouse // over pixmap/mask (XmNraisedPixmap/XmNraisedMask) are created and used. // // The XfeButton will render the insensitive effect for the pixmap // automatically. Also, the button will be filled on arm. This provides // enough "mouse-down" feedback and thus reduces the XID resource // consumption (pixmaps and pixels). // ////////////////////////////////////////////////////////////////////////// /* extern */ void fe_buttonSetPixmaps(Widget button,IconGroup * ig) { XP_ASSERT( ig != NULL ); XP_ASSERT( XfeIsAlive(button) ); XP_ASSERT( XfeIsButton(button) ); if (!ig || !XfeIsAlive(button)) { return; } // Use the closest ancestor shell's colormap Widget shell_for_colormap = XfeAncestorFindByClass(button,shellWidgetClass,XfeFIND_ANY); XP_ASSERT( XfeIsAlive(shell_for_colormap) ); // Normal pixmap if (!XfePixmapGood(ig->pixmap_icon.pixmap)) { IconGroup_createOneIcon(&ig->pixmap_icon, ig->pixmap_data, shell_for_colormap, XfeForeground(button), XfeBackground(button)); } // Mouse Over pixmap (raised) if (!XfePixmapGood(ig->pixmap_mo_icon.pixmap)) { IconGroup_createOneIcon(&ig->pixmap_mo_icon, ig->pixmap_mo_data, shell_for_colormap, XfeForeground(button), XfeBackground(button)); } Arg av[4]; Cardinal ac = 0; // XmNpixmap if (XfePixmapGood(ig->pixmap_icon.pixmap)) { XtSetArg(av[ac],XmNpixmap,ig->pixmap_icon.pixmap); ac++; } // XmNpixmapMask if (XfePixmapGood(ig->pixmap_icon.mask)) { XtSetArg(av[ac],XmNpixmapMask,ig->pixmap_icon.mask); ac++; } // XmNraisedPixmap if (XfePixmapGood(ig->pixmap_mo_icon.pixmap)) { XtSetArg(av[ac],XmNraisedPixmap,ig->pixmap_mo_icon.pixmap); ac++; } // XmNraisedPixmapMask if (XfePixmapGood(ig->pixmap_mo_icon.mask)) { XtSetArg(av[ac],XmNraisedPixmapMask,ig->pixmap_mo_icon.mask); ac++; } if (ac) { XtSetValues(button,av,ac); } } //////////////////////////////////////////////////////////////////////////