home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / ToolbarDrop.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  13.6 KB  |  482 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /*---------------------------------------*/
  19. /*                                                                        */
  20. /* Name:        ToolbarDrop.cpp                                            */
  21. /* Description:    Classes to support drop stuff on toolbars.                */
  22. /* Author:        Ramiro Estrugo <ramiro@netscape.com>                    */
  23. /*                                                                        */
  24. /*----------------------------------------------------------------------*/
  25.  
  26.  
  27.  
  28. #include "PersonalToolbar.h"
  29. #include "ToolbarDrop.h"
  30. #include "BookmarkMenu.h"
  31. #include "MozillaApp.h"
  32.  
  33. #include <Xfe/Cascade.h>
  34. #include <Xfe/Button.h>
  35. #include <Xfe/ToolBar.h>
  36. #include <Xfe/BmButton.h>
  37. #include <Xfe/BmCascade.h>
  38.  
  39. #ifdef DEBUG_ramiro
  40. #define XDEBUG(x) x
  41. #else
  42. #define XDEBUG(x)
  43. #endif
  44.  
  45. // cancels timer which loads homepage after sploosh screen (mozilla.c)
  46. extern "C" void plonk_cancel();
  47.  
  48. //
  49. // XFE_ToolbarDrop class
  50. //
  51.  
  52. // Amount of time in ms to wait before posting a personal/quickfile popup.
  53. // This delay is required for dnd operations that originate in a foreign
  54. // shell and cause focus in/out events which in turn might cause window 
  55. // managers (such as fvwm) to auti-raise a window.  This would cover the
  56. // popup menu making it useless.
  57. #define DROP_POST_SLEEP_LENGTH 1000
  58.  
  59. //////////////////////////////////////////////////////////////////////////
  60. XFE_ToolbarDrop::XFE_ToolbarDrop(Widget parent)
  61.     : XFE_DropNetscape(parent)
  62. {
  63. }
  64. //////////////////////////////////////////////////////////////////////////
  65. XFE_ToolbarDrop::~XFE_ToolbarDrop()
  66. {
  67. }
  68. //////////////////////////////////////////////////////////////////////////
  69. void
  70. XFE_ToolbarDrop::targets()
  71. {
  72.     _numTargets=2;
  73.     _targets=new Atom[_numTargets];
  74.  
  75.     _targets[0]=_XA_NETSCAPE_URL;
  76.     _targets[1]=XA_STRING;
  77.  
  78.     acceptFileTargets();
  79. }
  80. //////////////////////////////////////////////////////////////////////////
  81. void
  82. XFE_ToolbarDrop::operations()
  83. {
  84.     // always copy - move/link irrelevant
  85.     _operations = (unsigned int) XmDROP_COPY;
  86. }
  87. //////////////////////////////////////////////////////////////////////////
  88. Boolean
  89. XFE_ToolbarDrop::isFromSameShell()
  90. {
  91.     // Check if this operation occurred in the same shell as the _widget
  92.     if (XFE_DragBase::_activeDragShell) 
  93.     {
  94.         Widget shell = _widget;
  95.  
  96.         while (!XtIsShell(shell))
  97.         {
  98.             shell=XtParent(shell);
  99.         }
  100.  
  101.         if (shell==XFE_DragBase::_activeDragShell)
  102.         {
  103.             return True;
  104.         }
  105.     }
  106.  
  107.  
  108.     return False;
  109. }
  110. //////////////////////////////////////////////////////////////////////////
  111. int
  112. XFE_ToolbarDrop::processTargets(Atom *            targets,
  113.                                 const char **    data,
  114.                                 int                numItems)
  115. {
  116.     XDEBUG(printf("XFE_ToolbarDrop::processTargets()\n"));
  117.     
  118.     if (!targets || !data || numItems==0)
  119.         return FALSE;
  120.  
  121.     // open dropped files in browser
  122.  
  123.     for (int i=0;i<numItems;i++) {
  124.         if (targets[i]==None || data[i]==NULL || strlen(data[i])==0)
  125.             continue;
  126.  
  127.         XDEBUG(printf("  [%d] %s: \"%s\"\n",i,XmGetAtomName(XtDisplay(_widget),targets[i]),data[i]));
  128.  
  129.         if (targets[i]==_XA_FILE_NAME) 
  130.         {
  131.             // "file:" + filename + \0
  132.             char *address=new char[5+strlen(data[i])+1]; 
  133.  
  134.             XP_SPRINTF(address,"file:%s",data[i]);
  135.  
  136.             if (address)
  137.             {
  138.                 plonk_cancel();
  139.  
  140.                 addEntry(address,NULL);
  141.  
  142.  
  143.                 delete address;
  144.             }
  145.         }
  146.         
  147.         if (targets[i]==_XA_NETSCAPE_URL) 
  148.         {
  149.             XFE_URLDesktopType urlData(data[i]);
  150.  
  151.             for (int j=0;j<urlData.numItems();j++) 
  152.             {
  153.                 if (urlData.url(j))
  154.                 {
  155.                     plonk_cancel();
  156.  
  157.                     addEntry(urlData.url(j),NULL);
  158.                 }
  159.             }
  160.         }
  161.  
  162.         if (targets[i]==XA_STRING) 
  163.         {
  164.             if (data[i])
  165.             {
  166.                 plonk_cancel();
  167.  
  168.                 addEntry(data[i],NULL);
  169.             }
  170.         }
  171.     }
  172.     
  173.     return TRUE;
  174. }
  175. //////////////////////////////////////////////////////////////////////////
  176. /* virtual */ void
  177. XFE_ToolbarDrop::addEntry(const char * /* address */,const char * /* title */)
  178. {
  179. }
  180. //////////////////////////////////////////////////////////////////////////
  181.  
  182. //
  183. // XFE_PersonalDrop class
  184. //
  185.  
  186. //////////////////////////////////////////////////////////////////////////
  187. XFE_PersonalDrop::XFE_PersonalDrop(Widget                    dropWidget, 
  188.                                    XFE_PersonalToolbar *    toolbar) :
  189.     XFE_ToolbarDrop(dropWidget),
  190.     _personalToolbar(toolbar),
  191.     _lastRaisedWidget(NULL),
  192.     _dropWidget(NULL)
  193. {
  194. }
  195. //////////////////////////////////////////////////////////////////////////
  196. XFE_PersonalDrop::~XFE_PersonalDrop()
  197. {
  198. }
  199. //////////////////////////////////////////////////////////////////////////
  200. /* virtual */ void
  201. XFE_PersonalDrop::addEntry(const char * address,const char * title)
  202. {
  203.     XP_ASSERT( address != NULL );
  204.  
  205.     XP_ASSERT( XfeIsAlive(_dropWidget) );
  206.     XP_ASSERT( _personalToolbar != NULL );
  207.  
  208.     char *        guessed_title = (char *) title;
  209.     BM_Date        lastAccess = 0;
  210.  
  211.     // If no title is given, try to guess a decent one
  212.     if (!guessed_title)
  213.     {
  214.         XFE_BookmarkBase::guessTitle(_personalToolbar->getFrame(),
  215.                                      _personalToolbar->getBookmarkContext(),
  216.                                      address,
  217.                                      isFromSameShell(),
  218.                                      &guessed_title,
  219.                                      &lastAccess);
  220.     }
  221.  
  222.     XP_ASSERT( guessed_title != NULL );
  223.  
  224.     // If the drop occurred on a cascade item, then we need to waid for 
  225.     // the drop operation to complete before posting the submenu id and 
  226.     // allowing the user to place the new bookmark.  This will happen
  227.     // in dropCompolete().  Here, we just install the drop parameters that
  228.     // the personal toolbar will use when adding the new bookmark.
  229.     if (XfeIsCascade(_dropWidget))
  230.     {
  231.         BM_Entry * entry = (BM_Entry *) XfeUserData(_dropWidget);
  232.  
  233. //         XP_ASSERT( entry != NULL );
  234. //         XP_ASSERT( BM_IsHeader(entry) );
  235.  
  236.         // If the folder is empty, then just add the new bm to it
  237.         if (entry && BM_IsHeader(entry) && !BM_GetChildren(entry))
  238.         {
  239.             _personalToolbar->addEntryToFolder(address,
  240.                                                guessed_title,
  241.                                                lastAccess,
  242.                                                entry);
  243.             
  244.             _dropWidget = NULL;
  245.         }
  246.         // Otherwise need to popup the bookmark placement gui later
  247.         else
  248.         {
  249.             _personalToolbar->setDropAddress(address);
  250.             _personalToolbar->setDropTitle(guessed_title);
  251.             _personalToolbar->setDropLastAccess(lastAccess);
  252.         }
  253.     }
  254.     // If the drop occurred on a button, then we add the new bookmark
  255.     // at the position of the previous item
  256.     else if (XfeIsButton(_dropWidget))
  257.     {
  258.         BM_Entry * entry = (BM_Entry *) XfeUserData(_dropWidget);
  259.  
  260.         if (entry)
  261.         {
  262.             _personalToolbar->addEntryBefore(address,
  263.                                              guessed_title,
  264.                                              lastAccess,
  265.                                              entry);
  266.         }
  267.         else
  268.         {
  269.             _personalToolbar->addEntry(address,guessed_title,lastAccess);
  270.         }
  271.  
  272.         // Clear the drop widget so that dropComplete() does not get hosed
  273.         _dropWidget = NULL;
  274.      }
  275.     // If the drop occurred anywhere else on the personal toolbar, then
  276.     // we simple add the new bookmark at the end of the toolbar.
  277.     else if (XfeIsToolBar(_dropWidget))
  278.     {
  279.         _personalToolbar->addEntry(address,guessed_title,lastAccess);
  280.  
  281.         // Clear the drop widget so that dropComplete() does not get hosed
  282.         _dropWidget = NULL;
  283.     }
  284. }
  285. //////////////////////////////////////////////////////////////////////////
  286. /* virtual */ void
  287. XFE_PersonalDrop::dropComplete()
  288. {
  289.     // If the drop widget is still alive and kicking, it means that a drop
  290.     // occurred on a cascade item.  Here we deal with this unique case.
  291.     if (XfeIsAlive(_dropWidget) && XfeIsSensitive(_dropWidget))
  292.     {
  293.         // App is now busy
  294.         XFE_MozillaApp::theApp()->notifyInterested(XFE_MozillaApp::appBusyCallback);
  295.  
  296.         // Sleep for a while so that the drop site has time to "recover"
  297.         // as well as allow time for the parent shell of the drop widget to
  298.         // get focus if the drop originated in a different shell and 
  299.         // the user's window manager is configured to auto-raise windows
  300.         XfeSleep(_dropWidget,fe_EventLoop,DROP_POST_SLEEP_LENGTH);
  301.  
  302.         // Enable dropping into the personal toolbar
  303.         _personalToolbar->enableDropping();
  304.  
  305.         // Arm and post the cascade.  Once the cascade button's submenu id
  306.         // is posted, the bookmark menu items it manages will detect
  307.         // that the accent has been enabled (previous statement) and
  308.         // instead of behaving as a normal menu, will allow the user to
  309.         // place the bookmark in an arbitrary position within the
  310.         // personal toolbar.
  311.          XfeCascadeArmAndPost(_dropWidget,NULL);
  312.  
  313.         // App is not busy anymore
  314.         XFE_MozillaApp::theApp()->notifyInterested(XFE_MozillaApp::appNotBusyCallback);
  315.     }
  316.  
  317.     // Clear the drop widget since we are now done with it for sure
  318.     _dropWidget = NULL;
  319. }
  320. //////////////////////////////////////////////////////////////////////////
  321. /* virtual */ void
  322. XFE_PersonalDrop::dragIn()
  323. {
  324.     dragMotion();
  325. }
  326. //////////////////////////////////////////////////////////////////////////
  327. /* virtual */ void
  328. XFE_PersonalDrop::dragOut()
  329. {
  330.     _dropWidget = NULL;
  331.  
  332.     if (XfeIsAlive(_lastRaisedWidget))
  333.     {
  334.         XtVaSetValues(_lastRaisedWidget,XmNraised,False,NULL);
  335.  
  336.         _dropWidget = _lastRaisedWidget;
  337.     }
  338.  
  339.     _lastRaisedWidget = NULL;
  340. }
  341. //////////////////////////////////////////////////////////////////////////
  342. /* virtual */ void
  343. XFE_PersonalDrop::dragMotion()
  344. {
  345.     Widget raised = getRaisedWidget();
  346.  
  347.     if (raised == _lastRaisedWidget)
  348.     {
  349.         return;
  350.     }
  351.  
  352.     if (XfeIsAlive(_lastRaisedWidget))
  353.     {
  354.         XtVaSetValues(_lastRaisedWidget,XmNraised,False,NULL);
  355.     }
  356.  
  357.     _lastRaisedWidget = raised;
  358.  
  359.     if (XfeIsAlive(_lastRaisedWidget))
  360.     {
  361.         XtVaSetValues(_lastRaisedWidget,XmNraised,True,NULL);
  362.     }
  363. }
  364. //////////////////////////////////////////////////////////////////////////
  365. Widget
  366. XFE_PersonalDrop::getRaisedWidget()
  367. {
  368.     Widget raised = XfeDescendantFindByCoordinates(_widget,
  369.                                                    _dropEventX,
  370.                                                    _dropEventY);
  371.  
  372.     if (!raised)
  373.     {
  374.         raised = _widget;
  375.     }
  376.  
  377.     if (!XfeIsSensitive(raised))
  378.     {
  379.         raised = _widget;
  380.     }
  381.  
  382.     return raised;
  383. }
  384. //////////////////////////////////////////////////////////////////////////
  385.  
  386.  
  387. //
  388. // XFE_QuickfileDrop class
  389. //
  390.  
  391. //////////////////////////////////////////////////////////////////////////
  392. XFE_QuickfileDrop::XFE_QuickfileDrop(Widget                    dropWidget,
  393.                                      XFE_BookmarkMenu *        quickfileMenu) :
  394.     XFE_ToolbarDrop(dropWidget),
  395.     _quickfileMenu(quickfileMenu)
  396. {
  397. }
  398. //////////////////////////////////////////////////////////////////////////
  399. XFE_QuickfileDrop::~XFE_QuickfileDrop()
  400. {
  401. }
  402. //////////////////////////////////////////////////////////////////////////
  403. /* virtual */ void
  404. XFE_QuickfileDrop::addEntry(const char * address,const char * title)
  405. {
  406.     XP_ASSERT( address != NULL );
  407.  
  408.     XP_ASSERT( XfeIsAlive(_widget) );
  409.     XP_ASSERT( _quickfileMenu != NULL );
  410.  
  411.     char *        guessed_title = (char *) title;
  412.     BM_Date        lastAccess = 0;
  413.  
  414.     // If no title is given, try to guess a decent one
  415.     if (!guessed_title)
  416.     {
  417.         XFE_BookmarkBase::guessTitle(_quickfileMenu->getFrame(),
  418.                                      _quickfileMenu->getBookmarkContext(),
  419.                                      address,
  420.                                      isFromSameShell(),
  421.                                      &guessed_title,
  422.                                      &lastAccess);
  423.     }
  424.  
  425.     XP_ASSERT( guessed_title != NULL );
  426.  
  427.      _quickfileMenu->setDropAddress(address);
  428.      _quickfileMenu->setDropTitle(guessed_title);
  429.      _quickfileMenu->setDropLastAccess(lastAccess);
  430. }
  431. //////////////////////////////////////////////////////////////////////////
  432. /* virtual */ void
  433. XFE_QuickfileDrop::dragIn()
  434. {
  435.     if (XfeIsSensitive(_widget))
  436.     {
  437.         XtVaSetValues(_widget,XmNraised,True,NULL);
  438.     }
  439. }
  440. //////////////////////////////////////////////////////////////////////////
  441. /* virtual */ void
  442. XFE_QuickfileDrop::dragOut()
  443. {
  444.     if (XfeIsSensitive(_widget))
  445.     {
  446.         XtVaSetValues(_widget,XmNraised,False,NULL);
  447.     }
  448. }
  449. //////////////////////////////////////////////////////////////////////////
  450. /* virtual */ void
  451. XFE_QuickfileDrop::dropComplete()
  452. {
  453.     // If the drop widget is still alive and kicking, it means that a drop
  454.     // occurred on a cascade item.  Here we deal with this unique case.
  455.     if (XfeIsAlive(_widget) && XfeIsSensitive(_widget))
  456.     {
  457.         // App is now busy
  458.         XFE_MozillaApp::theApp()->notifyInterested(XFE_MozillaApp::appBusyCallback);
  459.  
  460.         // Sleep for a while so that the drop site has time to "recover"
  461.         // as well as allow time for the parent shell of the drop widget to
  462.         // get focus if the drop originated in a different shell and 
  463.         // the user's window manager is configured to auto-raise windows
  464.         XfeSleep(_widget,fe_EventLoop,DROP_POST_SLEEP_LENGTH);
  465.  
  466.         // Enable dropping into the quickfile menu
  467.         _quickfileMenu->enableDropping();
  468.  
  469.         // Arm and post the cascade.  Once the cascade button's submenu id
  470.         // is posted, the bookmark menu items it manages will detect
  471.         // that the accent has been enabled (previous statement) and
  472.         // instead of behaving as a normal menu, will allow the user to
  473.         // place the bookmark in an arbitrary position within the
  474.         // personal toolbar.
  475.          XfeCascadeArmAndPost(_widget,NULL);
  476.  
  477.         // App is not busy anymore
  478.         XFE_MozillaApp::theApp()->notifyInterested(XFE_MozillaApp::appNotBusyCallback);
  479.     }
  480. }
  481. //////////////////////////////////////////////////////////////////////////
  482.