/* * Motif * * Copyright (c) 1987-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these librararies and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include "BaseClassI.h" #include "ToolTipI.h" #include "XmI.h" #ifdef FIX_1388 static void ToolTipLabelDestroyCallback(Widget w, XtPointer client_data, XtPointer call_data) { XmToolTipConfigTrait ttcp; ttcp = (XmToolTipConfigTrait) XmeTraitGet(w, XmQTtoolTipConfig); if (ttcp != NULL) if (ttcp->label != NULL) { Widget shell = XtParent(ttcp->label); XtDestroyWidget(ttcp->label); ttcp->label = NULL; XtDestroyWidget(shell); } } #endif /* FIX_1388 */ static XmToolTipConfigTrait ToolTipGetData (Widget w) { Widget top = w; XmToolTipConfigTrait ttp; while (XtParent (top)) { top = XtParent (top); } ttp = (XmToolTipConfigTrait) XmeTraitGet (top, XmQTtoolTipConfig); if (ttp != NULL && ttp->label == NULL && !top->core.being_destroyed) { Widget shell; shell = XtVaCreateWidget ("TipShell", transientShellWidgetClass, top, XmNoverrideRedirect, True, NULL); ttp->label = XmCreateLabel (shell, "TipLabel", NULL, 0); XtManageChild (ttp->label); #ifdef FIX_1388 XtAddCallback(top, XmNdestroyCallback, (XtCallbackProc) ToolTipLabelDestroyCallback, (XtPointer) NULL); #endif } return ttp; } static void ToolTipUnpost (XtPointer client_data, XtIntervalId * id) { XmToolTipConfigTrait ttp; ttp = (XmToolTipConfigTrait) client_data; if (ttp->duration_timer) { if (!id || (id && (*id != ttp->duration_timer))) { XtRemoveTimeOut (ttp->duration_timer); } ttp->duration_timer = (XtIntervalId) NULL; } if (ttp->slider) { XtDestroyWidget (ttp->slider); ttp->slider = NULL; } if (ttp->label != NULL && !XtParent (ttp->label)->core.being_destroyed) { XtPopdown (XtParent (ttp->label)); } } static void ToolTipPostFinish (Widget slide, XtPointer client_data, XtPointer call_data) { XmToolTipConfigTrait ttp; ttp = (XmToolTipConfigTrait) client_data; if (ttp == NULL) { XtWarning ("ToolTipPostFinish() - ttp==NULL"); return; } ttp->slider = NULL; if (ttp->post_duration > 0) { ttp->duration_timer = XtAppAddTimeOut (XtWidgetToApplicationContext (ttp->label), (unsigned long) ttp->post_duration, (XtTimerCallbackProc) ToolTipUnpost, client_data); } } static void ToolTipPost (XtPointer client_data, XtIntervalId * id) { Widget w = (Widget) client_data; int rx, ry, x, y; unsigned int key; Window root, child; XtWidgetGeometry geo; Position destX, destY; XmToolTipConfigTrait ttp; /* ToolTip pointer */ ttp = ToolTipGetData (w); if (ttp == NULL) { XtWarning ("ToolTipGetData() returned NULL in ToolTipPost()"); return; } ttp->timer = (XtIntervalId) NULL; XQueryPointer (XtDisplay (w), XtWindow (w), &root, &child, &rx, &ry, &x, &y, &key); if (ttp->duration_timer != (XtIntervalId) NULL) { XtRemoveTimeOut (ttp->duration_timer); ttp->duration_timer = (XtIntervalId) NULL; } if (XmIsPrimitive(w) || XmIsGadget(w)) { XtVaSetValues (ttp->label, XmNlabelString, XmGetToolTipString(w), NULL); } else { XmString string; string = XmStringCreateLocalized (XtName (w)); XtVaSetValues (ttp->label, XmNlabelString, string, NULL); XmStringFree (string); } XtQueryGeometry (ttp->label, NULL, &geo); /* rws 25 Feb 2001 Fix for Bug #1153 Don't let the tip be off the right/bottom of the screen */ destX = rx + (XmIsGadget (w) ? XtX (w) : 0) - x + XtWidth (w) / 2; if (destX + geo.width > WidthOfScreen (XtScreen (w))) { destX = WidthOfScreen (XtScreen (w)) - geo.width; } destY = ry + (XmIsGadget (w) ? XtY (w) : 0) - y + XtHeight (w); if (destY + geo.height > HeightOfScreen (XtScreen (w))) { destY = ry + (XmIsGadget (w) ? XtY (w) : 0) - y - geo.height; } XtVaSetValues (XtParent (ttp->label), XmNx, rx + 1, XmNy, ry + 1, XmNwidth, 1, XmNheight, 1, NULL); ttp->slider = XtVaCreateWidget ("ToolTipSlider", xmSlideContextWidgetClass, XmGetXmDisplay (XtDisplay (w)), XmNslideWidget, XtParent (ttp->label), XmNslideDestX, destX, XmNslideDestY, destY, XmNslideDestWidth, geo.width, XmNslideDestHeight, geo.height, NULL); XtAddCallback (ttp->slider, XmNslideFinishCallback, (XtCallbackProc) ToolTipPostFinish, ttp); XtPopup (XtParent (ttp->label), XtGrabNone); } /* ===================================== Publically available functions follow ===================================== */ void _XmToolTipEnter (Widget wid, XEvent * event, String * params, Cardinal * num_params) { XmToolTipConfigTrait ttp; /* ToolTip pointer */ ttp = ToolTipGetData (wid); if (ttp == NULL) { XtWarning ("ToolTipGetData() returned NULL in _XmToolTipEnter()"); return; } if ((XmIsPrimitive (wid) || XmIsGadget(wid)) && XmGetToolTipString(wid)) { if (ttp->enable && !ttp->timer) { unsigned long delay; if (event && (event->xcrossing.time - ttp->leave_time < ttp->post_delay)) { delay = 0; } else { delay = (unsigned long) ttp->post_delay; } if (ttp->duration_timer) { XtRemoveTimeOut (ttp->duration_timer); ttp->duration_timer = (XtIntervalId) NULL; } ttp->timer = XtAppAddTimeOut (XtWidgetToApplicationContext (wid), delay, (XtTimerCallbackProc) ToolTipPost, wid); } } } void _XmToolTipLeave (Widget w, XEvent * event, String * params, Cardinal * num_params) { XmToolTipConfigTrait ttp = ToolTipGetData (w); if (!ttp) { XtWarning ("_XmToolTipLeave() - ttp == NULL."); return; } if (ttp->timer) { XtRemoveTimeOut (ttp->timer); ttp->timer = (XtIntervalId) NULL; } else { if (event && (ttp->duration_timer || ttp->post_duration == 0)) { ttp->leave_time = event->xcrossing.time; } ToolTipUnpost (ttp, NULL); } } #ifdef FIX_1388 void _XmToolTipRemove(Widget w) { XmToolTipTrait ttp; _XmToolTipLeave(w, NULL, NULL, NULL); ttp = (XmToolTipTrait) XmeTraitGet(w, XmQTtoolTip); if (ttp != NULL) { XmStringFree(ttp->tool_tip_string); XmeTraitSet(w, XmQTtoolTip, (XtPointer) NULL); XtFree((char*)ttp); } } #endif /* FIX_1388 */ Widget XmToolTipGetLabel(Widget wid) { XmToolTipConfigTrait TipData = ToolTipGetData(wid); #ifdef BUG1232 /* rws 25 Sep 2003 protect against NULL TipData */ #endif return(TipData ? TipData->label : NULL); } XmString XmGetToolTipString (Widget w) { XmToolTipTrait ttp; ttp = (XmToolTipTrait)XmeTraitGet(w, XmQTtoolTip); return ttp ? ttp->tool_tip_string : NULL; } void XmSetToolTipString (Widget w, XmString s) { XmToolTipTrait ttp; ttp = (XmToolTipTrait)XmeTraitGet(w, XmQTtoolTip); if (!ttp) { ttp = (XmToolTipTrait)XtCalloc(1, sizeof(XmToolTipTraitRec)); XmeTraitSet(w, XmQTtoolTip, ttp); } if (ttp->tool_tip_string) XmStringFree(ttp->tool_tip_string); ttp->tool_tip_string = XmStringCopy(s); }