/* -*- 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. */ /*---------------------------------------*/ /* */ /* Name: PersonalToolbar.cpp */ /* Description: XFE_PersonalToolbar component source. */ /* Author: Ramiro Estrugo */ /* */ /*----------------------------------------------------------------------*/ #include "structs.h" #include "xfe.h" #include "xpassert.h" #include "bkmks.h" #include "felocale.h" #include "intl_csi.h" #include "prefapi.h" #include "View.h" #include "PersonalToolbar.h" #include "MozillaApp.h" #include "BookmarkFrame.h" #include "BookmarkMenu.h" #include "IconGroup.h" #include "ToolbarDrop.h" #include "Logo.h" #include "PopupMenu.h" #include "prefapi.h" #include #include #define DEFAULT_TOOLBAR_FOLDER_NAME "Personal Toolbar Folder" #define MIN_TOOLBAR_HEIGHT 26 #define MAX_CHILD_WIDTH 100 #define PERSONAL_TOOLBAR_NAME "personalToolbar" #define LOGO_NAME "logo" /* static */ MenuSpec XFE_PersonalToolbar::m_popupMenuSpec[] = { { xfeCmdPersonalToolbarAddBookmark, PUSHBUTTON }, { xfeCmdPersonalToolbarEditItem, PUSHBUTTON }, { xfeCmdPersonalToolbarRemoveItem, PUSHBUTTON }, MENU_SEPARATOR, { xfeCmdPersonalToolbarItemProperties, PUSHBUTTON }, { NULL } }; ////////////////////////////////////////////////////////////////////////// XFE_PersonalToolbar::XFE_PersonalToolbar(MWContext * bookmarkContext, XFE_Toolbox * parent_toolbox, const char * name, XFE_Frame * frame) : XFE_ToolboxItem(frame,parent_toolbox), XFE_BookmarkBase(bookmarkContext,frame,False,True), m_toolBarFolder(NULL), m_toolBarDropSite(NULL), m_openedTabDropSite(NULL), m_closedTabDropSite(NULL), m_dropTargetItem(NULL), m_dropTargetLocation(XmINDICATOR_LOCATION_NONE), m_popup(NULL) { XP_ASSERT( name != NULL ); XP_ASSERT( getBookmarkContext() != NULL ); // Obtain the toolbar folder m_toolBarFolder = XFE_PersonalToolbar::getToolbarFolder(); // Create the base widget - a tool item m_widget = XtVaCreateWidget(name, xfeToolItemWidgetClass, parent_toolbox->getBaseWidget(), XmNuserData, this, NULL); // Create the toolbar m_toolBar = XtVaCreateManagedWidget(PERSONAL_TOOLBAR_NAME, xfeToolBarWidgetClass, m_widget, XmNusePreferredWidth, False, XmNusePreferredHeight, True, XmNchildForceWidth, False, XmNchildForceHeight, True, XmNchildUsePreferredWidth, True, XmNchildUsePreferredHeight, False, NULL); // Create the logo m_logo = new XFE_Logo(getFrame(),m_widget,LOGO_NAME); m_logo->setSize(XFE_ANIMATION_SMALL); // Attach and configure the logo configureLogo(); // Update the appearace for the first time updateAppearance(); // Make sure the toolbar is not highlighted first setRaised(False); // Register and enable the toolbar drop site m_toolBarDropSite = new XFE_PersonalDrop(m_toolBar,this); m_toolBarDropSite->enable(); // Get the toolbox parent tabs Widget opened_tab = parent_toolbox->tabOfItem(m_widget,True); Widget closed_tab = parent_toolbox->tabOfItem(m_widget,False); XP_ASSERT( XfeIsAlive(opened_tab) ); XP_ASSERT( XfeIsAlive(closed_tab) ); // Register and enable the tab drop sites m_openedTabDropSite = new XFE_PersonalTabDrop(opened_tab,this); m_closedTabDropSite = new XFE_PersonalTabDrop(closed_tab,this); m_openedTabDropSite->enable(); m_closedTabDropSite->enable(); // Configure the drop sites Arg xargs[1]; Cardinal n = 0; XtSetArg(xargs[n],XmNanimationStyle, XmDRAG_UNDER_NONE); n++; m_toolBarDropSite->update(xargs,n); m_openedTabDropSite->update(xargs,n); m_closedTabDropSite->update(xargs,n); // Register personal toolbar widgets for dragging addDragWidget(getBaseWidget()); addDragWidget(getToolBarWidget()); // Install the destruction handler installDestroyHandler(); // Force the items to update reallyUpdateRoot(); // If we are supposed to have a toolbar folder, but it does not // exist, then we need to create one and populate it with the default // crap from marketing if (XFE_PersonalToolbar::hasToolbarFolder() && !m_toolBarFolder) { addDefaultToolbarFolder(); XP_ASSERT( isToolbarFolderValid() ); if (isToolbarFolderValid()) { addDefaultPersonalEntries("personal_toolbar",m_toolBarFolder); } } // Add popup callback to toolbar XtAddCallback(m_toolBar, XmNbutton3DownCallback, &XFE_PersonalToolbar::popupCB, (XtPointer) this); } ////////////////////////////////////////////////////////////////////////// XFE_PersonalToolbar::~XFE_PersonalToolbar() { if (m_toolBarDropSite) { delete m_toolBarDropSite; } if (m_openedTabDropSite) { delete m_openedTabDropSite; } if (m_closedTabDropSite) { delete m_closedTabDropSite; } if (m_popup) { delete m_popup; } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// /* virtual */ void XFE_PersonalToolbar::prepareToUpdateRoot() { // Force the items to update reallyUpdateRoot(); } ////////////////////////////////////////////////////////////////////////// /* virtual */ void XFE_PersonalToolbar::reallyUpdateRoot() { BM_Entry * newFolder = XFE_PersonalToolbar::getToolbarFolder(); // Check for changes in the toolbar folder if (m_toolBarFolder != newFolder) { #ifdef DEBUG_slamm XP_ASSERT(newFolder); #endif if (newFolder) XFE_PersonalToolbar::setToolbarFolder(newFolder,False); m_toolBarFolder = newFolder; } // Since a lot of changes will happen to the toolbar, we tell it to // any geometry or layout changes. We will force these to occur later. XtVaSetValues(m_toolBar,XmNignoreConfigure,True,NULL); // Destroy the current widgets destroyToolbarWidgets(); // If the toolbar folder is valid, populate the toolbar if (isToolbarFolderValid()) { // Access the first entry in the personal toolbar folder BM_Entry * entry = BM_GetChildren(m_toolBarFolder); while (entry) { Widget item = NULL; // Headers if (BM_IsHeader(entry)) { item = createXfeCascade(m_toolBar,entry); } // Separators else if (BM_IsSeparator(entry)) { item = createSeparator(m_toolBar); } // Normal items else { item = createXfeButton(m_toolBar,entry); } XP_ASSERT( XfeIsAlive(item) ); XtManageChild(item); entry = BM_GetNext(entry); } } // Tell the toolbar not too ignore geometry or layout changes anymore XtVaSetValues(m_toolBar,XmNignoreConfigure,False,NULL); // Force the toolbar to reconfigure. XfeManagerLayout(m_toolBar); } ////////////////////////////////////////////////////////////////////////// /* virtual */ void XFE_PersonalToolbar::configureXfeButton(Widget item,BM_Entry *entry) { if (fe_globalPrefs.toolbar_style == BROWSER_TOOLBAR_TEXT_ONLY) { XtVaSetValues(item, XmNpixmap, XmUNSPECIFIED_PIXMAP, XmNpixmapMask, XmUNSPECIFIED_PIXMAP, NULL); XtVaSetValues(item,XmNbuttonLayout,XmBUTTON_LABEL_ONLY,NULL); } else { Pixmap pixmap; Pixmap pixmapMask; getPixmapsForEntry(entry,&pixmap,&pixmapMask,NULL,NULL); XtVaSetValues(item, XmNpixmap, pixmap, XmNpixmapMask, pixmapMask, XmNbuttonLayout, XmBUTTON_LABEL_ON_RIGHT, NULL); } // Add popup callback to item XtAddCallback(item, XmNbutton3DownCallback, &XFE_PersonalToolbar::popupCB, (XtPointer) this); } ////////////////////////////////////////////////////////////////////////// /* virtual */ void XFE_PersonalToolbar::configureXfeCascade(Widget item,BM_Entry * entry) { if (fe_globalPrefs.toolbar_style == BROWSER_TOOLBAR_TEXT_ONLY) { XtVaSetValues(item, XmNpixmap, XmUNSPECIFIED_PIXMAP, XmNarmedPixmap, XmUNSPECIFIED_PIXMAP, XmNpixmapMask, XmUNSPECIFIED_PIXMAP, XmNarmedPixmapMask, XmUNSPECIFIED_PIXMAP, NULL); // XtVaSetValues(item,XmNbuttonLayout,XmBUTTON_LABEL_ONLY,NULL); } else { Pixmap pixmap; Pixmap armedPixmap; Pixmap pixmapMask; Pixmap armedPixmapMask; Arg av[4]; Cardinal ac = 0; getPixmapsForEntry(entry,&pixmap,&pixmapMask, &armedPixmap,&armedPixmapMask); XtSetArg(av[ac],XmNpixmap, pixmap); ac++; XtSetArg(av[ac],XmNpixmapMask, pixmapMask); ac++; // Only show the aremd pixmap/mask if this entry has children if (XfeIsAlive(XfeCascadeGetSubMenu(item))) { XtSetArg(av[ac],XmNarmedPixmap, armedPixmap); ac++; XtSetArg(av[ac],XmNarmedPixmapMask, armedPixmapMask); ac++; } XtSetValues(item,av,ac); // XtVaSetValues(item,XmNbuttonLayout,XmBUTTON_LABEL_ON_RIGHT,NULL); } // Add popup callback to item XtAddCallback(item, XmNbutton3DownCallback, &XFE_PersonalToolbar::popupCB, (XtPointer) this); } ////////////////////////////////////////////////////////////////////////// /* virtual */ void XFE_PersonalToolbar::updateAppearance() { if (fe_globalPrefs.toolbar_style == BROWSER_TOOLBAR_TEXT_ONLY) { XtVaSetValues(m_toolBar,XmNbuttonLayout,XmBUTTON_LABEL_ONLY,NULL); } else { XtVaSetValues(m_toolBar,XmNbuttonLayout,XmBUTTON_LABEL_ON_RIGHT,NULL); } reallyUpdateRoot(); } ////////////////////////////////////////////////////////////////////////// /* virtual */ void XFE_PersonalToolbar::updateToolbarFolderName() { // Access the new toolbar folder BM_Entry * newFolder = XFE_PersonalToolbar::getToolbarFolder(); // Make sure the folder has indeed changed if (m_toolBarFolder != newFolder) { // Assign the new toolbar folder m_toolBarFolder = newFolder; // Update reallyUpdateRoot(); } } ////////////////////////////////////////////////////////////////////////// void XFE_PersonalToolbar::addDefaultPersonalEntries(char * configString, BM_Entry * header) { int i = 0; XP_Bool ok = PREF_NOERROR; char * label; char * url; BM_Entry * entry; char curConfigString[256]; XP_SPRINTF(curConfigString,"%s.item",configString); for (i=0; ok==PREF_NOERROR; i++) { label = url = NULL; ok = PREF_CopyIndexConfigString(curConfigString,i,"label",&label); if (ok == PREF_NOERROR) { ok = PREF_CopyIndexConfigString(curConfigString,i,"url",&url); if(ok == PREF_NOERROR) { // if it's a folder we need to first fill it in if(XP_STRCMP(url, "FOLDER")== 0) { entry = BM_NewHeader(label); char buf[256]; XP_SPRINTF(buf,"%s_%d",curConfigString,i); addDefaultPersonalEntries(buf,entry); } // otherwise just create a new url else { entry = BM_NewUrl(label,url,NULL,0); } //add the new entry BM_AppendToHeader(getBookmarkContext(),header,entry); } } if(label) { XP_FREE(label); } if(url) { XP_FREE(url); } } } ////////////////////////////////////////////////////////////////////////// Widget XFE_PersonalToolbar::getToolBarWidget() { return m_toolBar; } ////////////////////////////////////////////////////////////////////////// Widget XFE_PersonalToolbar::getFirstItem() { return XfeToolBarGetFirstItem(m_toolBar); } ////////////////////////////////////////////////////////////////////////// Widget XFE_PersonalToolbar::getLastItem() { return XfeToolBarGetLastItem(m_toolBar); } ////////////////////////////////////////////////////////////////////////// Widget XFE_PersonalToolbar::getIndicatorItem() { return XfeToolBarGetIndicatorItem(m_toolBar); } ////////////////////////////////////////////////////////////////////////// void XFE_PersonalToolbar::configureIndicatorItem(BM_Entry * /* entry */) { Widget indicator = getIndicatorItem(); if (XfeIsAlive(indicator)) { if (fe_globalPrefs.toolbar_style == BROWSER_TOOLBAR_TEXT_ONLY) { XtVaSetValues(indicator, XmNpixmap, XmUNSPECIFIED_PIXMAP, XmNpixmapMask, XmUNSPECIFIED_PIXMAP, XmNbuttonLayout, XmBUTTON_LABEL_ONLY, NULL); } else { Pixmap pixmap; Pixmap pixmapMask; XFE_BookmarkBase::getBookmarkPixmaps(pixmap,pixmapMask); XtVaSetValues(indicator, XmNpixmap, pixmap, XmNpixmapMask, pixmapMask, XmNbuttonLayout, XmBUTTON_LABEL_ON_RIGHT, NULL); } } } ////////////////////////////////////////////////////////////////////////// void XFE_PersonalToolbar::setRaised(XP_Bool state) { XP_ASSERT( XfeIsAlive(m_toolBar) ); XtVaSetValues(m_toolBar,XmNraised,state,NULL); } ////////////////////////////////////////////////////////////////////////// void XFE_PersonalToolbar::addEntry(const char * address, const char * title, BM_Date lastAccess) { XP_ASSERT( address != NULL ); XP_ASSERT( title != NULL ); // If there is no personal toolbar folder add a default one if (!m_toolBarFolder) { addDefaultToolbarFolder(); } XP_ASSERT( isToolbarFolderValid() ); if (!isToolbarFolderValid()) { return; } BM_Entry * entry = BM_NewUrl(title,address,NULL,lastAccess); BM_AppendToHeader(getBookmarkContext(),m_toolBarFolder,entry); } ////////////////////////////////////////////////////////////////////////// void XFE_PersonalToolbar::destroyToolbarWidgets() { XP_ASSERT( XfeIsAlive(m_toolBar) ); WidgetList children; Cardinal num_children; XfeChildrenGet(m_toolBar,&children,&num_children); // Get rid of the previous items we created if (children && num_children) { XtUnmanageChildren(children,num_children); XfeDestroyMenuWidgetTree(children,num_children,True); } } ////////////////////////////////////////////////////////////////////////// void XFE_PersonalToolbar::addDefaultToolbarFolder() { // First, look for a folder called "Personal Toolbar Folder" BM_Entry * folder = getTopLevelFolder(DEFAULT_TOOLBAR_FOLDER_NAME); if (!folder) { folder = BM_NewHeader(DEFAULT_TOOLBAR_FOLDER_NAME); BM_AppendToHeader(getBookmarkContext(), getRootFolder(), // BM_GetAddHeader(getBookmarkContext()), folder); } XFE_PersonalToolbar::setToolbarFolder(folder,True); } ////////////////////////////////////////////////////////////////////////// XP_Bool XFE_PersonalToolbar::isToolbarFolderValid() { return ((m_toolBarFolder != NULL) && BM_IsHeader(m_toolBarFolder)); } ////////////////////////////////////////////////////////////////////////// /* static */ void XFE_PersonalToolbar::setToolbarFolder(BM_Entry * entry,XP_Bool notify) { char * name = ""; XP_Bool has_folder = False; // Assign the name if the entry is valid if (entry && BM_IsHeader(entry)) { name = BM_GetName(entry); has_folder = True; } // Set the preferences StrAllocCopy(fe_globalPrefs.personal_toolbar_folder, name); fe_globalPrefs.has_toolbar_folder = has_folder; // Notify mozilla app that the personal toolbar folder has changed. if (notify) { XFE_MozillaApp::theApp()->notifyInterested( XFE_MozillaApp::personalToolbarFolderChanged); } } ////////////////////////////////////////////////////////////////////////// /* static */ BM_Entry * XFE_PersonalToolbar::getToolbarFolder() { BM_Entry * result = NULL; if (!XFE_BookmarkFrame::main_bm_context) { return NULL; } // Access the toolbar folder name char * name = XFE_PersonalToolbar::getToolbarFolderName(); // Try to find the folder to match the name if (name) { BM_Entry * root = BM_GetRoot(XFE_BookmarkFrame::main_bm_context); XP_ASSERT( root != NULL ); if (root) { result = XFE_BookmarkBase::BM_FindFolderByName(root,name); } } return result; } ////////////////////////////////////////////////////////////////////////// /* static */ XP_Bool XFE_PersonalToolbar::hasToolbarFolder() { // Find out if we do have a toolbar folder return fe_globalPrefs.has_toolbar_folder; } ////////////////////////////////////////////////////////////////////////// /* static */ char * XFE_PersonalToolbar::getToolbarFolderName() { // Make sure the main bookmark context is valid if (!XFE_BookmarkFrame::main_bm_context) { return NULL; } // Make sure we have a toolbar folder defined if (!XFE_PersonalToolbar::hasToolbarFolder()) { return NULL; } // Find out the name of the toolbar folder return fe_globalPrefs.personal_toolbar_folder; } ////////////////////////////////////////////////////////////////////////// // // DND feedback methods // Widget XFE_PersonalToolbar::getDropTargetItem() { return m_dropTargetItem; } ////////////////////////////////////////////////////////////////////////// unsigned char XFE_PersonalToolbar::getDropTargetLocation() { return m_dropTargetLocation; } ////////////////////////////////////////////////////////////////////////// void XFE_PersonalToolbar::setDropTargetItem(Widget item,int x) { assert( XfeIsAlive(item) ); m_dropTargetItem = item; m_dropTargetLocation = XfeToolBarXYToIndicatorLocation(m_toolBar, m_dropTargetItem, x,0); int position = XfeChildGetIndex(m_dropTargetItem); XtVaSetValues(m_toolBar, XmNindicatorPosition, position, XmNindicatorLocation, m_dropTargetLocation, NULL); } ////////////////////////////////////////////////////////////////////////// void XFE_PersonalToolbar::clearDropTargetItem() { m_dropTargetItem = NULL; XtVaSetValues(m_toolBar, XmNindicatorPosition, XmINDICATOR_DONT_SHOW, NULL); } ////////////////////////////////////////////////////////////////////////// // // Popup menu stuff // /* static */ void XFE_PersonalToolbar::popupCB(Widget w, XtPointer clientData, XtPointer callData) { XFE_PersonalToolbar * pt = (XFE_PersonalToolbar *) clientData; XmAnyCallbackStruct * cbs = (XmAnyCallbackStruct *) callData; XEvent * event = cbs->event; pt->handlePopup(w,event); } ////////////////////////////////////////////////////////////////////////// void XFE_PersonalToolbar::handlePopup(Widget w,XEvent * event) { if (!m_popup) { m_popup = new XFE_PopupMenu("popup",getFrame(),FE_GetToplevelWidget()); m_popup->setMenuSpec(XFE_PersonalToolbar::m_popupMenuSpec); } if (XfeIsButton(w)) { printf("Button Popup(%s)\n",XtName(w)); } else if (XfeIsToolBar(w)) { printf("ToolBar Popup(%s)\n",XtName(w)); } m_popup->position(event); m_popup->show(); // BM_Entry * entry; } //////////////////////////////////////////////////////////////////////////