Files
Mozilla/mozilla/cmd/xfe/src/ToolbarDrop.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

589 lines
16 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):
*/
/*---------------------------------------*/
/* */
/* Name: ToolbarDrop.cpp */
/* Description: Classes to support drop stuff on toolbars. */
/* Author: Ramiro Estrugo <ramiro@netscape.com> */
/* */
/*----------------------------------------------------------------------*/
#include "MozillaApp.h"
#include "ToolbarDrop.h"
#include "ToolbarItem.h"
#include "BookmarkMenu.h"
#include "htrdf.h"
#include "RDFToolbar.h"
#include "RDFUtils.h"
#include <Xfe/Cascade.h>
#include <Xfe/Button.h>
#include <Xfe/ToolBar.h>
#include <Xfe/Tab.h>
#include <Xfe/BmButton.h>
#include <Xfe/BmCascade.h>
#ifdef DEBUG_ramiro
#define XDEBUG(x) x
#else
#define XDEBUG(x)
#endif
// cancels timer which loads homepage after sploosh screen (mozilla.c)
extern "C" void plonk_cancel();
//
// XFE_ToolbarDrop class
//
// Amount of time in ms to wait before posting a personal/quickfile popup.
// This delay is required for dnd operations that originate in a foreign
// shell and cause focus in/out events which in turn might cause window
// managers (such as fvwm) to auti-raise a window. This would cover the
// popup menu making it useless.
#define DROP_POST_SLEEP_LENGTH 1000
//////////////////////////////////////////////////////////////////////////
XFE_ToolbarDrop::XFE_ToolbarDrop(Widget parent)
: XFE_DropNetscape(parent)
{
}
//////////////////////////////////////////////////////////////////////////
XFE_ToolbarDrop::~XFE_ToolbarDrop()
{
}
//////////////////////////////////////////////////////////////////////////
void
XFE_ToolbarDrop::targets()
{
_numTargets=2;
_targets=new Atom[_numTargets];
_targets[0]=_XA_NETSCAPE_URL;
_targets[1]=XA_STRING;
acceptFileTargets();
}
//////////////////////////////////////////////////////////////////////////
void
XFE_ToolbarDrop::operations()
{
// always copy - move/link irrelevant
_operations = (unsigned int) XmDROP_COPY;
}
//////////////////////////////////////////////////////////////////////////
Boolean
XFE_ToolbarDrop::isFromSameShell()
{
// Check if this operation occurred in the same shell as the _widget
if (XFE_DragBase::_activeDragShell)
{
Widget shell = _widget;
while (!XtIsShell(shell))
{
shell=XtParent(shell);
}
if (shell==XFE_DragBase::_activeDragShell)
{
return True;
}
}
return False;
}
//////////////////////////////////////////////////////////////////////////
int
XFE_ToolbarDrop::processTargets(Atom * targets,
const char ** data,
int numItems)
{
XDEBUG(printf("XFE_ToolbarDrop::processTargets()\n"));
if (!targets || !data || numItems==0)
return FALSE;
// open dropped files in browser
for (int i=0;i<numItems;i++) {
if (targets[i]==None || data[i]==NULL || strlen(data[i])==0)
continue;
XDEBUG(printf(" [%d] %s: \"%s\"\n",i,XmGetAtomName(XtDisplay(_widget),targets[i]),data[i]));
if (targets[i]==_XA_FILE_NAME)
{
// "file:" + filename + \0
char *address=new char[5+strlen(data[i])+1];
XP_SPRINTF(address,"file:%s",data[i]);
if (address)
{
plonk_cancel();
addEntry(address,NULL);
delete address;
}
}
if (targets[i]==_XA_NETSCAPE_URL)
{
XFE_URLDesktopType urlData(data[i]);
for (int j=0;j<urlData.numItems();j++)
{
if (urlData.url(j))
{
plonk_cancel();
addEntry(urlData.url(j),NULL);
}
}
}
if (targets[i]==XA_STRING)
{
if (data[i])
{
plonk_cancel();
addEntry(data[i],NULL);
}
}
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_ToolbarDrop::addEntry(const char * /* address */,const char * /* title */)
{
}
//////////////////////////////////////////////////////////////////////////
//
// XFE_RDFToolbarDrop class
//
//////////////////////////////////////////////////////////////////////////
XFE_RDFToolbarDrop::XFE_RDFToolbarDrop(Widget dropWidget,
XFE_RDFToolbar * toolbar) :
XFE_ToolbarDrop(dropWidget),
_toolbar(toolbar),
_dropWidget(NULL)
{
}
//////////////////////////////////////////////////////////////////////////
XFE_RDFToolbarDrop::~XFE_RDFToolbarDrop()
{
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_RDFToolbarDrop::addEntry(const char * address, const char * title)
{
XP_ASSERT( address != NULL );
XP_ASSERT( XfeIsAlive(_dropWidget) );
XP_ASSERT( _toolbar != NULL );
unsigned char location = _toolbar->getDropTargetLocation();
// If the drop occurred on a cascade item, then we need to wait for
// the drop operation to complete before posting the submenu id and
// allowing the user to place the new bookmark. This will happen
// in dropCompolete(). Here, we just install the drop parameters that
// the personal toolbar will use when adding the new bookmark.
if (XfeIsCascade(_dropWidget))
{
HT_Resource entry = (HT_Resource) XfeUserData(_dropWidget);
if (entry != NULL)
{
if (location == XmINDICATOR_LOCATION_BEGINNING)
{
HT_DropURLAndTitleAtPos(entry, (char*)address, (char*)title, TRUE);
// Clear drop widget so dropComplete() does not get hosed
_dropWidget = NULL;
}
else if (location == XmINDICATOR_LOCATION_END)
{
HT_DropURLAndTitleAtPos(entry, (char*)address, (char*)title, FALSE);
// Clear drop widget so dropComplete() does not get hosed
_dropWidget = NULL;
}
else if (location == XmINDICATOR_LOCATION_MIDDLE)
{
// If the folder is empty, then just add the new bm to it
if (HT_IsContainer(entry)
&& !XFE_RDFUtils::ht_FolderHasChildren(entry))
{
HT_DropURLAndTitleOn(entry,(char*)address, (char*)title);
// Clear drop widget so dropComplete() does not get hosed
_dropWidget = NULL;
}
// Otherwise need to popup the bookmark placement gui later
else
{
_toolbar->setDropAddress((char*)address);
_toolbar->setDropTitle((char*)title);
}
}
}
}
// If the drop occurred on a button, then we add the new bookmark
// at the position of the previous item
else if (XfeIsButton(_dropWidget))
{
HT_Resource entry = (HT_Resource) XfeUserData(_dropWidget);
if (entry)
{
if (location == XmINDICATOR_LOCATION_BEGINNING)
{
HT_DropURLAndTitleAtPos(entry, (char*)address, (char*)title, TRUE);
}
else if (location == XmINDICATOR_LOCATION_END)
{
HT_DropURLAndTitleAtPos(entry, (char*)address, (char*)title, FALSE);
}
else
{
HT_DropURLAndTitleAtPos(entry, (char*)address, (char*)title, FALSE);
}
}
// Clear the drop widget so that dropComplete() does not get hosed
_dropWidget = NULL;
}
// Other toolbar items - should not get here
else
{
// Separators (and maybe other items) are going to be a problem
// hmmmm...
XP_ASSERT( 0 );
// Clear the drop widget so that dropComplete() does not get hosed
_dropWidget = NULL;
}
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_RDFToolbarDrop::dropComplete()
{
_toolbar->clearDropTargetItem();
// If the drop widget is still alive and kicking, it means that a drop
// occurred on a cascade item. Here we deal with this unique case.
if (XfeIsAlive(_dropWidget) && XfeIsSensitive(_dropWidget))
{
// App is now busy
XFE_MozillaApp::theApp()->notifyInterested(XFE_MozillaApp::appBusyCallback);
// Sleep for a while so that the drop site has time to "recover"
// as well as allow time for the parent shell of the drop widget to
// get focus if the drop originated in a different shell and
// the user's window manager is configured to auto-raise windows
XfeSleep(_dropWidget,fe_EventLoop,DROP_POST_SLEEP_LENGTH);
// Enable dropping into the personal toolbar
_toolbar->enableDropping();
// Arm and post the cascade. Once the cascade button's submenu id
// is posted, the bookmark menu items it manages will detect
// that the accent has been enabled (previous statement) and
// instead of behaving as a normal menu, will allow the user to
// place the bookmark in an arbitrary position within the
// personal toolbar.
XfeCascadeArmAndPost(_dropWidget,NULL);
// App is not busy anymore
XFE_MozillaApp::theApp()->notifyInterested(XFE_MozillaApp::appNotBusyCallback);
}
// Clear the drop widget since we are now done with it for sure
_dropWidget = NULL;
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_RDFToolbarDrop::dragIn()
{
dragMotion();
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_RDFToolbarDrop::dragOut()
{
_dropWidget = _toolbar->getDropTargetItem();
_toolbar->clearDropTargetItem();
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_RDFToolbarDrop::dragMotion()
{
// Try to find an item at the X,Y that the motion occured
Widget target = XfeDescendantFindByCoordinates(_widget,
_dropEventX,
_dropEventY);
// If we found the indicator, ignore it
if (target != _toolbar->getIndicatorItem())
{
// If an item is found, use it as the target
if (XfeIsAlive(target))
{
_toolbar->setDropTargetItem(target, _dropEventX - XfeX(target));
_toolbar->configureIndicatorItem(NULL);
}
// Otherwise use the last item
else
{
Widget last = _toolbar->getLastItem();
// The 10000 forces the position to be at the END of the item
if (XfeIsAlive(last))
{
_toolbar->setDropTargetItem(last,10000);
_toolbar->configureIndicatorItem(NULL);
}
}
}
// Assign the drop widget so that addEntry() can do its magic
_dropWidget = _toolbar->getDropTargetItem();
}
//////////////////////////////////////////////////////////////////////////
#if 0
//
// XFE_PersonalTabDrop class
//
//////////////////////////////////////////////////////////////////////////
XFE_PersonalTabDrop::XFE_PersonalTabDrop(Widget dropWidget,
XFE_PersonalToolbar * toolbar) :
XFE_RDFToolbarDrop(dropWidget,toolbar)
{
}
//////////////////////////////////////////////////////////////////////////
XFE_PersonalTabDrop::~XFE_PersonalTabDrop()
{
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_PersonalTabDrop::addEntry(const char * address,const char * title)
{
XP_ASSERT( address != NULL );
XP_ASSERT( _toolbar != NULL );
char * guessed_title = (char *) title;
time_t lastAccess = 0;
// If no title is given, try to guess a decent one
if (!guessed_title)
{
XFE_BookmarkBase::guessTitle(_toolbar->getFrame(),
address,
isFromSameShell(),
&guessed_title,
&lastAccess);
}
XP_ASSERT( guessed_title != NULL );
HT_Resource personal_folder = XFE_PersonalToolbar::getToolbarFolder();
if (personal_folder)
{
// Access the first entry in the personal toolbar folder
HT_Resource entry = BM_GetChildren(personal_folder);
// If the first entry exists, add the new entry before it
if (entry)
{
_toolbar->addEntryBefore(address,
guessed_title,
lastAccess,
entry);
}
// Otherwise add the entry to the personal toolbar folder
else
{
_toolbar->addEntry(address,guessed_title,lastAccess);
}
}
// Clear the drop widget so that dropComplete() does not get hosed
_dropWidget = NULL;
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_PersonalTabDrop::dropComplete()
{
// Nothing
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_PersonalTabDrop::dragIn()
{
Widget first = _toolbar->getFirstItem();
// The 0 forces the position to be at the first
if (XfeIsAlive(first))
{
_toolbar->setDropTargetItem(first,0);
// The argument should really be a (HT_Resource)
_toolbar->configureIndicatorItem(NULL);
}
XfeTabDrawRaised(_widget,True);
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_PersonalTabDrop::dragOut()
{
XfeTabDrawRaised(_widget,False);
_toolbar->clearDropTargetItem();
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_PersonalTabDrop::dragMotion()
{
// Nothing
}
//////////////////////////////////////////////////////////////////////////
#endif /*0*/
//
// XFE_QuickfileDrop class
//
//////////////////////////////////////////////////////////////////////////
XFE_QuickfileDrop::XFE_QuickfileDrop(Widget dropWidget,
XFE_BookmarkMenu * quickfileMenu) :
XFE_ToolbarDrop(dropWidget),
_quickfileMenu(quickfileMenu)
{
}
//////////////////////////////////////////////////////////////////////////
XFE_QuickfileDrop::~XFE_QuickfileDrop()
{
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_QuickfileDrop::addEntry(const char * address,const char * title)
{
XP_ASSERT( address != NULL );
XP_ASSERT( XfeIsAlive(_widget) );
XP_ASSERT( _quickfileMenu != NULL );
char * guessed_title = (char *) title;
time_t lastAccess = 0;
// If no title is given, try to guess a decent one
if (!guessed_title)
{
MWContext * context = _quickfileMenu->getFrame()->getContext();
XFE_RDFUtils::guessTitle(context,
address,
isFromSameShell(),
&guessed_title,
&lastAccess);
}
XP_ASSERT( guessed_title != NULL );
_quickfileMenu->setDropAddress(address);
_quickfileMenu->setDropTitle(guessed_title);
_quickfileMenu->setDropLastAccess(lastAccess);
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_QuickfileDrop::dragIn()
{
if (XfeIsSensitive(_widget))
{
XtVaSetValues(_widget,XmNraised,True,NULL);
}
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_QuickfileDrop::dragOut()
{
if (XfeIsSensitive(_widget))
{
XtVaSetValues(_widget,XmNraised,False,NULL);
}
}
//////////////////////////////////////////////////////////////////////////
/* virtual */ void
XFE_QuickfileDrop::dropComplete()
{
// If the drop widget is still alive and kicking, it means that a drop
// occurred on a cascade item. Here we deal with this unique case.
if (XfeIsAlive(_widget) && XfeIsSensitive(_widget))
{
// App is now busy
XFE_MozillaApp::theApp()->notifyInterested(XFE_MozillaApp::appBusyCallback);
// Sleep for a while so that the drop site has time to "recover"
// as well as allow time for the parent shell of the drop widget to
// get focus if the drop originated in a different shell and
// the user's window manager is configured to auto-raise windows
XfeSleep(_widget,fe_EventLoop,DROP_POST_SLEEP_LENGTH);
// Enable dropping into the quickfile menu
_quickfileMenu->enableDropping();
// Arm and post the cascade. Once the cascade button's submenu id
// is posted, the bookmark menu items it manages will detect
// that the accent has been enabled (previous statement) and
// instead of behaving as a normal menu, will allow the user to
// place the bookmark in an arbitrary position within the
// personal toolbar.
XfeCascadeArmAndPost(_widget,NULL);
// App is not busy anymore
XFE_MozillaApp::theApp()->notifyInterested(XFE_MozillaApp::appNotBusyCallback);
}
}
//////////////////////////////////////////////////////////////////////////