Mozilla/mozilla/cmd/xfe/src/ProxyIcon.cpp
dmose%mozilla.org 83e38c06cc updated license boilerplate to xPL v1.1
git-svn-id: svn://10.0.0.236/trunk@52594 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-02 22:43:10 +00:00

258 lines
6.1 KiB
C++

/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
ProxyIcon.cpp -- a label that you can drag from.
Created: Chris Toshok <toshok@netscape.com>, 1-Dec-96.
*/
#include "ProxyIcon.h"
#include <Xm/Label.h>
#define NONMOTIF_DND
#ifdef DEBUG_toshok
#define D(x) x
#else
#define D(x)
#endif
#if defined(USE_MOTIF_DND)
fe_dnd_Source _xfe_dragsource = { 0 };
#else
extern fe_dnd_Source _xfe_dragsource;
#endif /* USE_MOTIF_DND */
XFE_ProxyIcon::XFE_ProxyIcon(XFE_Component *toplevel_component,
Widget parent, char *name, fe_icon *icon)
: XFE_Component(toplevel_component)
{
Widget label;
m_icon = icon;
m_toplevel = toplevel_component;
label = XmCreateLabel(parent, name, NULL, 0);
setBaseWidget(label);
XtInsertEventHandler(label, ButtonPressMask | ButtonReleaseMask
| PointerMotionMask, False,
buttonEventHandler, this, XtListHead);
m_activity = 0;
m_lastmotionx =
m_lastmotiony = 0;
m_dragtype = FE_DND_NONE;
setIcon(icon);
}
void
XFE_ProxyIcon::setIcon(fe_icon *icon)
{
m_icon = icon;
if (m_icon && m_icon->pixmap)
{
XtVaSetValues(m_widget,
XmNlabelType, XmPIXMAP,
XmNlabelPixmap, icon->pixmap,
NULL);
}
}
fe_icon *
XFE_ProxyIcon::getIcon()
{
return m_icon;
}
void
XFE_ProxyIcon::setDragType(fe_dnd_Type dragtype, XFE_Component *drag_source,
fe_dnd_SourceDropFunc sourcedropfunc)
{
m_dragtype = dragtype;
m_source = drag_source;
m_sourcedropfunc = sourcedropfunc;
}
void
XFE_ProxyIcon::makeDragWidget(int x, int y)
{
Visual *v = 0;
Colormap cmap = 0;
Cardinal depth = 0;
Widget label;
// fe_icon *icon;
Widget shell;
Pixmap dragPixmap;
D(printf("hot (x,y) = (%d,%d)\n", x, y);)
if (_xfe_dragsource.widget) return;
shell = m_toplevel->getBaseWidget();
XtVaGetValues (shell, XtNvisual, &v, XtNcolormap, &cmap,
XtNdepth, &depth, 0);
_xfe_dragsource.type = m_dragtype; // XXX column drags happen when the row was a header.
_xfe_dragsource.hotx = x;
_xfe_dragsource.hoty = y;
_xfe_dragsource.closure = m_dragtype == FE_DND_COLUMN ? (void*)this : (void*)m_source;
_xfe_dragsource.func = m_sourcedropfunc;
XP_ASSERT(m_icon != NULL);
if (m_icon == NULL) return;
dragPixmap = m_icon->pixmap;
_xfe_dragsource.widget = XtVaCreateWidget("drag_win",
overrideShellWidgetClass,
m_widget,
XmNwidth, m_icon->width,
XmNheight, m_icon->height,
XmNvisual, v,
XmNcolormap, cmap,
XmNdepth, depth,
XmNborderWidth, 0,
NULL);
label = XtVaCreateManagedWidget ("label",
xmLabelWidgetClass,
_xfe_dragsource.widget,
XmNlabelType, XmPIXMAP,
XmNlabelPixmap, dragPixmap,
NULL);
}
void
XFE_ProxyIcon::destroyDragWidget()
{
if (!_xfe_dragsource.widget) return;
XtDestroyWidget (_xfe_dragsource.widget);
_xfe_dragsource.widget = NULL;
}
void
XFE_ProxyIcon::buttonEvent(XEvent *event, Boolean *c)
{
int x = event->xbutton.x;
int y = event->xbutton.y;
m_ignoreevents = False;
switch (event->type)
{
case ButtonPress:
D(printf ("ButtonPress\n");)
/* Always ignore btn3. Btn3 is for popups. - dp */
if (event->xbutton.button == 3) break;
m_activity |= ButtonPressMask;
m_ignoreevents = True;
m_lastmotionx = x;
m_lastmotiony = y;
// Save this position off so we can draw the widget
// with the appropriate hot spot. Ie, you should drag
// the icon from the point where you clicked on it, not
// some predetermined hot spot..
m_hotSpot_x = x;
m_hotSpot_y = y;
break;
case ButtonRelease:
if (m_activity & ButtonPressMask)
{
if (m_activity & PointerMotionMask)
{
/* handle the drop */
fe_dnd_DoDrag(&_xfe_dragsource, event, FE_DND_DROP);
fe_dnd_DoDrag(&_xfe_dragsource, event, FE_DND_END);
destroyDragWidget();
}
}
m_activity = 0;
break;
#ifdef NONMOTIF_DND
case MotionNotify:
if (m_dragtype == FE_DND_NONE)
break;
if (!(m_activity & PointerMotionMask) &&
(abs(x - m_lastmotionx) < 5 && abs(y - m_lastmotiony) < 5))
{
/* We aren't yet dragging, and the mouse hasn't moved enough for
this to be considered a drag. */
break;
}
if (m_activity & ButtonPressMask)
{
/* ok, the pointer moved while a button was held.
* we're gonna drag some stuff.
*/
m_ignoreevents = True;
if (!(m_activity & PointerMotionMask))
{
// Create a drag source.
// We want the mouse-down location, not the last one.
makeDragWidget(m_hotSpot_x, m_hotSpot_y);
fe_dnd_DoDrag(&_xfe_dragsource, event, FE_DND_START);
m_activity |= PointerMotionMask;
}
fe_dnd_DoDrag(&_xfe_dragsource, event, FE_DND_DRAG);
/* Now, force all the additional mouse motion events that are
lingering around on the server to come to us, so that Xt can
compress them away. Yes, XSync really does improve performance
in this case, not hurt it. */
XSync(XtDisplay(m_widget), False);
}
m_lastmotionx = x;
m_lastmotiony = y;
break;
#endif
}
if (m_ignoreevents)
*c = False;
}
void
XFE_ProxyIcon::buttonEventHandler(Widget, XtPointer clientData, XEvent *event, Boolean *cont)
{
XFE_ProxyIcon *obj = (XFE_ProxyIcon*)clientData;
obj->buttonEvent(event, cont);
}