mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
316 lines
10 KiB
C++
316 lines
10 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.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.
|
|
*/
|
|
|
|
//
|
|
// CPersonalToolbarManager.cp
|
|
//
|
|
// Implementation of the CPersonalToolbarManager class which handles keeping all the
|
|
// personal toolbars in sync. This reads all its info from RDF, not the old BM UI.
|
|
//
|
|
// I REALLY dislike that most of this code is in Hungarian notation, but the Windows
|
|
// code that it originally came from was like that and instead of doing a slew of
|
|
// global replaces, I'll just complain about it.
|
|
//
|
|
|
|
#include "CPersonalToolbarManager.h"
|
|
#include "CPersonalToolbarTable.h"
|
|
#include "URDFUtilities.h"
|
|
|
|
#include "prefapi.h"
|
|
|
|
#pragma mark ¥¥ CPersonalToolbarManager
|
|
#pragma mark -- Public Methods
|
|
|
|
|
|
const char* CPersonalToolbarManager::kMaxButtonCharsPref = "browser.personal_toolbar_button.max_chars";
|
|
const char* CPersonalToolbarManager::kMinButtonCharsPref = "browser.personal_toolbar_button.min_chars";
|
|
|
|
|
|
//
|
|
// Constructor
|
|
//
|
|
// Setup. Assumes that preferences and RDF have been initialized fully by this point.
|
|
//
|
|
CPersonalToolbarManager :: CPersonalToolbarManager ( )
|
|
: mUserButtonInfoArray ( sizeof(CUserButtonInfo*) )
|
|
{
|
|
// setup our window into the RDF world and register this class as the one to be notified
|
|
// when the personal toolbar changes.
|
|
HT_Notification notifyStruct = CreateNotificationStruct();
|
|
mToolbarView = HT_GetSelectedView ( HT_NewPersonalToolbarPane(notifyStruct) );
|
|
Assert_(mToolbarView != NULL);
|
|
mToolbarRoot = HT_TopNode ( mToolbarView );
|
|
Assert_(mToolbarRoot != NULL);
|
|
HT_SetOpenState ( mToolbarRoot, PR_TRUE ); // ensure container is open so we can see its contents
|
|
|
|
// read in the maximum size we're allowing for personal toolbar items. If not
|
|
// found in prefs, use our own
|
|
int32 maxToolbarButtonChars, minToolbarButtonChars;
|
|
if ( PREF_GetIntPref(kMaxButtonCharsPref, &maxToolbarButtonChars ) == PREF_ERROR )
|
|
mMaxToolbarButtonChars = CPersonalToolbarManager::kMaxPersonalToolbarChars;
|
|
else
|
|
mMaxToolbarButtonChars = maxToolbarButtonChars;
|
|
if ( PREF_GetIntPref(kMinButtonCharsPref, &minToolbarButtonChars ) == PREF_ERROR )
|
|
mMinToolbarButtonChars = CPersonalToolbarManager::kMinPersonalToolbarChars;
|
|
else
|
|
mMinToolbarButtonChars = minToolbarButtonChars;
|
|
|
|
InitializeButtonInfo();
|
|
|
|
} // constructor
|
|
|
|
|
|
//
|
|
// Destructor
|
|
//
|
|
// The toolbars in individual windows will delete themselves when the window dies and
|
|
// unregister themselves as listeners. We don't need to do anything along those
|
|
// lines here.
|
|
//
|
|
CPersonalToolbarManager :: ~CPersonalToolbarManager ( )
|
|
{
|
|
//¥¥¥ delete the contents of the button list
|
|
} // destructor
|
|
|
|
|
|
//
|
|
// RegisterNewToolbar
|
|
//
|
|
// This must be called for each new toolbar created in a browser window. It fills in
|
|
// the toolbar with the correct items and registers it as a listener to the messages
|
|
// we emit.
|
|
//
|
|
void
|
|
CPersonalToolbarManager :: RegisterNewToolbar ( CPersonalToolbarTable* inBar )
|
|
{
|
|
AddListener ( inBar );
|
|
BroadcastMessage ( k_PTToolbarChanged );
|
|
|
|
} // RegisterNewToolbar
|
|
|
|
|
|
//
|
|
// ToolbarChanged
|
|
//
|
|
// The user has just made some change to the toolbar, such as manipulating items in the nav center
|
|
// or changing the personal toolbar folder. Since these changes could be quite extensive, we
|
|
// just clear out the whole thing and start afresh. Tell all the toolbars that they have to
|
|
// clear themselves and grab the new information. Changes to the toolbar directly, such as by
|
|
// drag and drop, are handled elsewhere.
|
|
//
|
|
void
|
|
CPersonalToolbarManager :: ToolbarChanged ( )
|
|
{
|
|
RemoveToolbarButtons(); // out with the old...
|
|
InitializeButtonInfo(); // ...in with the new
|
|
BroadcastMessage ( k_PTToolbarChanged );
|
|
|
|
} // ToolbarHeaderChanged
|
|
|
|
|
|
//
|
|
// AddButton
|
|
//
|
|
// Given a pre-created HT item, add it to the personal toolbar folder before the
|
|
// given id and tell all the toolbars to update. This is called when the user
|
|
// drops an item from another RDF source on a personal toolbar
|
|
//
|
|
void
|
|
CPersonalToolbarManager :: AddButton ( HT_Resource inBookmark, Uint32 inIndex )
|
|
{
|
|
// Add this to RDF.
|
|
if ( GetButtons().GetCount() ) {
|
|
// If we get back a null resource then we must be trying to drop after
|
|
// the last element, or there just plain aren't any in the toolbar. Re-fetch the last element
|
|
// (using the correct index) and add the new bookmark AFTER instead of before or just add
|
|
// it to the parent for the case of an empty toolbar
|
|
PRBool before = PR_TRUE;
|
|
HT_Resource dropOn = HT_GetNthItem( mToolbarView, URDFUtilities::PPRowToHTRow(inIndex) );
|
|
if ( ! dropOn ) {
|
|
dropOn = HT_GetNthItem( mToolbarView, URDFUtilities::PPRowToHTRow(inIndex) - 1 );
|
|
before = PR_FALSE;
|
|
}
|
|
HT_DropHTRAtPos ( dropOn, inBookmark, before );
|
|
} // if items in toolbar
|
|
else
|
|
HT_DropHTROn ( mToolbarRoot, inBookmark );
|
|
|
|
// no need to tell toolbars to refresh because we will get an HT node added event and
|
|
// refresh at that time.
|
|
|
|
} // Addbutton
|
|
|
|
|
|
//
|
|
// AddButton
|
|
//
|
|
// Given just a URL, add it to the personal toolbar folder before the
|
|
// given id and tell all the toolbars to update. This is called when the user
|
|
// drops an item from another RDF source on a personal toolbar
|
|
//
|
|
void
|
|
CPersonalToolbarManager :: AddButton ( const string & inURL, const string & inTitle, Uint32 inIndex )
|
|
{
|
|
// Add this to RDF.
|
|
if ( GetButtons().GetCount() ) {
|
|
// If we get back a null resource then we must be trying to drop after
|
|
// the last element, or there just plain aren't any in the toolbar. Re-fetch the last element
|
|
// (using the correct index) and add the new bookmark AFTER instead of before or just add
|
|
// it to the parent for the case of an empty toolbar
|
|
PRBool before = PR_TRUE;
|
|
HT_Resource dropOn = HT_GetNthItem( mToolbarView, URDFUtilities::PPRowToHTRow(inIndex) );
|
|
if ( ! dropOn ) {
|
|
dropOn = HT_GetNthItem( mToolbarView, URDFUtilities::PPRowToHTRow(inIndex) - 1 );
|
|
before = PR_FALSE;
|
|
}
|
|
HT_DropURLAndTitleAtPos ( dropOn, const_cast<char*>(inURL.c_str()),
|
|
const_cast<char*>(inTitle.c_str()), before );
|
|
} // if items in toolbar
|
|
else
|
|
HT_DropURLAndTitleOn ( mToolbarRoot, const_cast<char*>(inURL.c_str()),
|
|
const_cast<char*>(inTitle.c_str()) );
|
|
|
|
// no need to tell toolbars to refresh because we will get an HT node added event and
|
|
// refresh at that time.
|
|
|
|
} // Addbutton
|
|
|
|
|
|
//
|
|
// RemoveButton
|
|
//
|
|
// The user has explicitly removed a button from the toolbar in one of the windows (probably
|
|
// by dragging it to the trash). Tell all the other toolbars about it, remove it from our
|
|
// own bookkeeping list, then let RDF get rid of it.
|
|
//
|
|
void
|
|
CPersonalToolbarManager :: RemoveButton ( Uint32 inIndex )
|
|
{
|
|
CUserButtonInfo* deadBookmark;
|
|
GetButtons().FetchItemAt ( inIndex, &deadBookmark );
|
|
|
|
// remove it from RDF
|
|
HT_Resource deadNode = HT_GetNthItem ( GetHTView(), URDFUtilities::PPRowToHTRow(inIndex) );
|
|
HT_RemoveChild ( mToolbarRoot, deadNode );
|
|
|
|
delete deadBookmark;
|
|
|
|
// no need to tell toolbars to refresh because we will get an HT view update event and
|
|
// refresh at that time.
|
|
|
|
} // RemoveButton
|
|
|
|
|
|
//
|
|
// RemoveToolbarButtons
|
|
//
|
|
// Clears out our own internal list of toolbar button information.
|
|
//
|
|
void
|
|
CPersonalToolbarManager :: RemoveToolbarButtons (void)
|
|
{
|
|
mUserButtonInfoArray.RemoveItemsAt(mUserButtonInfoArray.GetCount(), LArray::index_First);
|
|
|
|
} // RemoveToolbarButtons
|
|
|
|
|
|
#pragma mark -- Protected Utility Methods
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// CPersonalToolbarManager Helpers
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//
|
|
// InitializeButtonInfo
|
|
//
|
|
// Create our list of information for each bookmark that belongs in the toolbar. This
|
|
// involves iterating over the RDF data in the folder pre-selected to be the personal
|
|
// toolbar folder, compiling some info about it, and adding to an internal list which
|
|
// will be used by each toolbar to build their tables.
|
|
//
|
|
// ¥¥¥NOTE: this will put folders in the bar if they exist. Strange things may happen if the
|
|
// user clicks on them....
|
|
//
|
|
void
|
|
CPersonalToolbarManager :: InitializeButtonInfo(void)
|
|
{
|
|
HT_Cursor cursor = HT_NewCursor( mToolbarRoot );
|
|
if ( cursor ) {
|
|
HT_Resource currNode = HT_GetNextItem(cursor);
|
|
while ( currNode ) {
|
|
CUserButtonInfo *info = new CUserButtonInfo ( HT_GetNodeName(currNode), HT_GetNodeURL(currNode),
|
|
0, 0, HT_IsContainer(currNode));
|
|
mUserButtonInfoArray.InsertItemsAt(1, LArray::index_Last, &info);
|
|
currNode = HT_GetNextItem(cursor);
|
|
} // for each top-level node
|
|
}
|
|
|
|
} // InitializeButtonInfo
|
|
|
|
|
|
//
|
|
// HandleNotification
|
|
//
|
|
// Called when the user makes a change to the personal toolbar folder from some other
|
|
// place (like the bookmarks view). Reset our internal list and tell our listeners
|
|
// that things are now different.
|
|
//
|
|
void
|
|
CPersonalToolbarManager :: HandleNotification(
|
|
HT_Notification /*notifyStruct*/,
|
|
HT_Resource node,
|
|
HT_Event event)
|
|
{
|
|
switch (event)
|
|
{
|
|
case HT_EVENT_NODE_ADDED:
|
|
case HT_EVENT_VIEW_REFRESH:
|
|
case HT_EVENT_NODE_VPROP_CHANGED:
|
|
{
|
|
// only update toolbar if the quickfile view changes
|
|
if ( HT_GetView(node) == mToolbarView )
|
|
ToolbarChanged();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#pragma mark ¥¥ class CUserButtonInfo
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// Class CUserButtonInfo
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CUserButtonInfo::CUserButtonInfo( const string & pName, const string & pURL, Uint32 nBitmapID,
|
|
Uint32 nBitmapIndex, bool bIsFolder)
|
|
: mName(pName), mURL(pURL), mBitmapID(nBitmapID), mBitmapIndex(nBitmapIndex),
|
|
mIsResourceID(true), mIsFolder(bIsFolder)
|
|
{
|
|
}
|
|
|
|
|
|
CUserButtonInfo::~CUserButtonInfo()
|
|
{
|
|
// string destructor takes care of everything...
|
|
}
|
|
|
|
|
|
|
|
|