зеркало из https://github.com/mozilla/pjs.git
Camino only - Bug 356488: Move GoMenu.{h,mm} to HistoryMenu.{h,mm}, and rename the GoMenu and HistoryMenu classes. sr=pink
This commit is contained in:
Родитель
625ef93d17
Коммит
91d0cd9dac
|
@ -354,7 +354,7 @@
|
|||
3F44AC9905BDFB9E00CB4B08 /* PreferenceManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = F52D5CD8027D3D5001A80166 /* PreferenceManager.mm */; };
|
||||
3F44AC9A05BDFB9E00CB4B08 /* HistoryDataSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = F52F87CD027D75C301A80165 /* HistoryDataSource.mm */; };
|
||||
3F44AC9C05BDFB9E00CB4B08 /* PageProxyIcon.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E2939FF027F33604B000102 /* PageProxyIcon.mm */; };
|
||||
3F44AC9D05BDFB9E00CB4B08 /* GoMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E748B73029A448D4B000102 /* GoMenu.mm */; };
|
||||
3F44AC9D05BDFB9E00CB4B08 /* HistoryMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E748B73029A448D4B000102 /* HistoryMenu.mm */; };
|
||||
3F44AC9D85BDFB9E00CB4B08 /* nsStaticComponents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56F241F02AC6D0401A967F3 /* nsStaticComponents.cpp */; };
|
||||
3F44AC9E05BDFB9E00CB4B08 /* BookmarkInfoController.mm in Sources */ = {isa = PBXBuildFile; fileRef = F53E012C02AEE93601A967F3 /* BookmarkInfoController.mm */; };
|
||||
3F44AC9F05BDFB9E00CB4B08 /* BrowserWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = F632AF8402B9AEBB01000103 /* BrowserWindow.mm */; };
|
||||
|
@ -633,7 +633,7 @@
|
|||
3F44AED205BDFBA000CB4B08 /* PreferenceManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = F52D5CD8027D3D5001A80166 /* PreferenceManager.mm */; };
|
||||
3F44AED305BDFBA000CB4B08 /* HistoryDataSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = F52F87CD027D75C301A80165 /* HistoryDataSource.mm */; };
|
||||
3F44AED505BDFBA000CB4B08 /* PageProxyIcon.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E2939FF027F33604B000102 /* PageProxyIcon.mm */; };
|
||||
3F44AED605BDFBA000CB4B08 /* GoMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E748B73029A448D4B000102 /* GoMenu.mm */; };
|
||||
3F44AED605BDFBA000CB4B08 /* HistoryMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E748B73029A448D4B000102 /* HistoryMenu.mm */; };
|
||||
3F44AED705BDFBA000CB4B08 /* nsStaticComponents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56F241F02AC6D0401A967F3 /* nsStaticComponents.cpp */; };
|
||||
3F44AED805BDFBA000CB4B08 /* BookmarkInfoController.mm in Sources */ = {isa = PBXBuildFile; fileRef = F53E012C02AEE93601A967F3 /* BookmarkInfoController.mm */; };
|
||||
3F44AED905BDFBA000CB4B08 /* AppDirServiceProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F59236C002C89AC90100012B /* AppDirServiceProvider.cpp */; };
|
||||
|
@ -2303,8 +2303,8 @@
|
|||
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
|
||||
2E2939FF027F33604B000102 /* PageProxyIcon.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = PageProxyIcon.mm; path = src/browser/PageProxyIcon.mm; sourceTree = "<group>"; };
|
||||
2E293A00027F33604B000102 /* PageProxyIcon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PageProxyIcon.h; path = src/browser/PageProxyIcon.h; sourceTree = "<group>"; };
|
||||
2E748B72029A448D4B000102 /* GoMenu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = GoMenu.h; path = src/browser/GoMenu.h; sourceTree = "<group>"; };
|
||||
2E748B73029A448D4B000102 /* GoMenu.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = GoMenu.mm; path = src/browser/GoMenu.mm; sourceTree = "<group>"; };
|
||||
2E748B72029A448D4B000102 /* HistoryMenu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = HistoryMenu.h; path = src/browser/HistoryMenu.h; sourceTree = "<group>"; };
|
||||
2E748B73029A448D4B000102 /* HistoryMenu.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = HistoryMenu.mm; path = src/browser/HistoryMenu.mm; sourceTree = "<group>"; };
|
||||
3312BF340C84C2B4000E6965 /* arrow.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; name = arrow.gif; path = ../dist/Embed/res/arrow.gif; sourceTree = SOURCE_ROOT; };
|
||||
3312BF350C84C2B4000E6965 /* arrowd.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; name = arrowd.gif; path = ../dist/Embed/res/arrowd.gif; sourceTree = SOURCE_ROOT; };
|
||||
3316F4470D11F1900025ED19 /* TabButtonView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = TabButtonView.h; path = src/browser/TabButtonView.h; sourceTree = "<group>"; };
|
||||
|
@ -3681,8 +3681,8 @@
|
|||
33563A540C84ED5800DC4D06 /* UI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2E748B72029A448D4B000102 /* GoMenu.h */,
|
||||
2E748B73029A448D4B000102 /* GoMenu.mm */,
|
||||
2E748B72029A448D4B000102 /* HistoryMenu.h */,
|
||||
2E748B73029A448D4B000102 /* HistoryMenu.mm */,
|
||||
335638FD0C84D82200DC4D06 /* HistoryOutlineViewDelegate.h */,
|
||||
0FBC0EDC0798F9B400E8E0E2 /* HistoryOutlineViewDelegate.mm */,
|
||||
);
|
||||
|
@ -5337,7 +5337,7 @@
|
|||
3F44AC9905BDFB9E00CB4B08 /* PreferenceManager.mm in Sources */,
|
||||
3F44AC9A05BDFB9E00CB4B08 /* HistoryDataSource.mm in Sources */,
|
||||
3F44AC9C05BDFB9E00CB4B08 /* PageProxyIcon.mm in Sources */,
|
||||
3F44AC9D05BDFB9E00CB4B08 /* GoMenu.mm in Sources */,
|
||||
3F44AC9D05BDFB9E00CB4B08 /* HistoryMenu.mm in Sources */,
|
||||
3F44AC9D85BDFB9E00CB4B08 /* nsStaticComponents.cpp in Sources */,
|
||||
3F44AC9E05BDFB9E00CB4B08 /* BookmarkInfoController.mm in Sources */,
|
||||
3F44AC9F05BDFB9E00CB4B08 /* BrowserWindow.mm in Sources */,
|
||||
|
@ -5518,7 +5518,7 @@
|
|||
3F44AED205BDFBA000CB4B08 /* PreferenceManager.mm in Sources */,
|
||||
3F44AED305BDFBA000CB4B08 /* HistoryDataSource.mm in Sources */,
|
||||
3F44AED505BDFBA000CB4B08 /* PageProxyIcon.mm in Sources */,
|
||||
3F44AED605BDFBA000CB4B08 /* GoMenu.mm in Sources */,
|
||||
3F44AED605BDFBA000CB4B08 /* HistoryMenu.mm in Sources */,
|
||||
3F44AED705BDFBA000CB4B08 /* nsStaticComponents.cpp in Sources */,
|
||||
3F44AED805BDFBA000CB4B08 /* BookmarkInfoController.mm in Sources */,
|
||||
3F44AED905BDFBA000CB4B08 /* AppDirServiceProvider.cpp in Sources */,
|
||||
|
|
|
@ -392,7 +392,7 @@
|
|||
/* History labels */
|
||||
"Tomorrow" = "Tomorrow";
|
||||
"Today" = "Today";
|
||||
"GoMenuEarlierToday" = "Earlier Today";
|
||||
"TopLevelHistoryMenuEarlierToday" = "Earlier Today";
|
||||
"Yesterday" = "Yesterday";
|
||||
"HistoryMoreThanAWeek" = "More than a week ago";
|
||||
"LocalFilesCategoryTitle" = "Local Files";
|
||||
|
|
|
@ -127,13 +127,7 @@
|
|||
LANGUAGE = ObjC;
|
||||
SUPERCLASS = NSObject;
|
||||
},
|
||||
{CLASS = GoMenu; LANGUAGE = ObjC; SUPERCLASS = HistoryMenu; },
|
||||
{
|
||||
CLASS = HistoryMenu;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {mItemBeforeHistoryItems = NSMenuItem; };
|
||||
SUPERCLASS = NSMenu;
|
||||
},
|
||||
{CLASS = HistorySubmenu; LANGUAGE = ObjC; SUPERCLASS = NSMenu; },
|
||||
{
|
||||
ACTIONS = {
|
||||
aboutPlugins = id;
|
||||
|
@ -231,6 +225,12 @@
|
|||
LANGUAGE = ObjC;
|
||||
OUTLETS = {mBrowserView = id; mWindow = id; };
|
||||
SUPERCLASS = NSObject;
|
||||
},
|
||||
{
|
||||
CLASS = TopLevelHistoryMenu;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {mItemBeforeHistoryItems = NSMenuItem; };
|
||||
SUPERCLASS = HistorySubmenu;
|
||||
}
|
||||
);
|
||||
IBVersion = 1;
|
||||
|
|
Двоичные данные
camino/resources/localized/English.lproj/MainMenu.nib/keyedobjects.nib
сгенерированный
Двоичные данные
camino/resources/localized/English.lproj/MainMenu.nib/keyedobjects.nib
сгенерированный
Двоичный файл не отображается.
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Mozilla browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Hewitt <hewitt@netscape.com> (Original Author)
|
||||
* Stuart Morgan <stuart.morgan@alumni.case.edu>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
@class HistoryItem;
|
||||
|
||||
// A class that builds and maintains a menu heirarchy parallel to some portion
|
||||
// of the history backend.
|
||||
@interface HistorySubmenu : NSMenu
|
||||
{
|
||||
HistoryItem* mRootItem; // root history item for this menu (retained)
|
||||
HistoryItem* mAdditionalItemsParent; // may also contain children of this item (retained)
|
||||
|
||||
int mNumIgnoreItems; // if > 0, ignore the first N items (for "earlier today")
|
||||
BOOL mHistoryItemsDirty; // whether we need to rebuild the items on next update
|
||||
}
|
||||
|
||||
// Sets the root history item that this menu represents.
|
||||
- (void)setRootHistoryItem:(HistoryItem*)inRootItem;
|
||||
|
||||
// Gets the root history item that this menu represents.
|
||||
- (HistoryItem*)rootItem;
|
||||
|
||||
// Sets the menu to skip displaying the first |inIgnoreItems| history items.
|
||||
- (void)setNumLeadingItemsToIgnore:(int)inIgnoreItems;
|
||||
|
||||
// Marks the history menu as needing to be rebuilt.
|
||||
- (void)setNeedsRebuild:(BOOL)needsRebuild;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// Encapsulates all of the logic of building, displaying, and handling the
|
||||
// top-level "History" menu.
|
||||
@interface TopLevelHistoryMenu : HistorySubmenu
|
||||
{
|
||||
IBOutlet NSMenuItem* mItemBeforeHistoryItems; // the item after which we add history items.
|
||||
HistoryItem* mTodayItem; // the "Today" history group
|
||||
|
||||
BOOL mAppLaunchDone; // has app launching completed?
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,524 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 the Mozilla browser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Joe Hewitt <hewitt@netscape.com> (Original Author)
|
||||
* Stuart Morgan <stuart.morgan@alumni.case.edu>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "HistoryMenu.h"
|
||||
|
||||
#import "NSString+Utils.h"
|
||||
#import "NSMenu+Utils.h"
|
||||
|
||||
#import "MainController.h"
|
||||
#import "BrowserWindowController.h"
|
||||
#import "CHBrowserService.h"
|
||||
#import "PreferenceManager.h"
|
||||
|
||||
#import "HistoryItem.h"
|
||||
#import "HistoryDataSource.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
// the maximum number of history entry menuitems to display
|
||||
static const int kMaxNumHistoryItems = 50;
|
||||
|
||||
// the maximum number of "today" items to show on the main menu
|
||||
static const unsigned int kMaxTodayItems = 12;
|
||||
|
||||
// the maximum number of characters in a menu title before cropping it
|
||||
static const unsigned int kMaxTitleLength = 50;
|
||||
|
||||
// this little class manages the singleton history data source, and takes
|
||||
// care of shutting it down at XPCOM shutdown time.
|
||||
@interface HistoryMenuDataSourceOwner : NSObject
|
||||
{
|
||||
HistoryDataSource* mHistoryDataSource;
|
||||
}
|
||||
|
||||
+ (HistoryMenuDataSourceOwner*)sharedHistoryMenuDataSourceOwner;
|
||||
+ (HistoryDataSource*)sharedHistoryDataSource; // just a shortcut
|
||||
|
||||
- (HistoryDataSource*)historyDataSource;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation HistoryMenuDataSourceOwner
|
||||
|
||||
+ (HistoryMenuDataSourceOwner*)sharedHistoryMenuDataSourceOwner
|
||||
{
|
||||
static HistoryMenuDataSourceOwner* sHistoryOwner = nil;
|
||||
if (!sHistoryOwner)
|
||||
sHistoryOwner = [[HistoryMenuDataSourceOwner alloc] init];
|
||||
|
||||
return sHistoryOwner;
|
||||
}
|
||||
|
||||
+ (HistoryDataSource*)sharedHistoryDataSource
|
||||
{
|
||||
return [[HistoryMenuDataSourceOwner sharedHistoryMenuDataSourceOwner] historyDataSource];
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
// register for xpcom shutdown
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(xpcomShutdownNotification:)
|
||||
name:XPCOMShutDownNotificationName
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[mHistoryDataSource release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)xpcomShutdownNotification:(NSNotification*)inNotification
|
||||
{
|
||||
[mHistoryDataSource release];
|
||||
mHistoryDataSource = nil;
|
||||
}
|
||||
|
||||
- (HistoryDataSource*)historyDataSource
|
||||
{
|
||||
if (!mHistoryDataSource) {
|
||||
mHistoryDataSource = [[HistoryDataSource alloc] init];
|
||||
[mHistoryDataSource setHistoryView:kHistoryViewByDate];
|
||||
[mHistoryDataSource setSortColumnIdentifier:@"last_visit"]; // always sort by last visit
|
||||
[mHistoryDataSource setSortDescending:YES];
|
||||
}
|
||||
return mHistoryDataSource;
|
||||
}
|
||||
|
||||
@end // HistoryMenuDataSourceOwner
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface HistorySubmenu(Private)
|
||||
|
||||
- (NSString*)menuItemTitleForHistoryItem:(HistoryItem*)inItem;
|
||||
|
||||
- (void)setupHistoryMenu;
|
||||
- (void)menuWillBeDisplayed;
|
||||
- (void)clearHistoryItems;
|
||||
- (void)rebuildHistoryItems;
|
||||
- (void)addLastItems;
|
||||
- (void)historyChanged:(NSNotification*)inNotification;
|
||||
- (void)menuWillDisplay:(NSNotification*)inNotification;
|
||||
- (void)openHistoryItem:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation HistorySubmenu
|
||||
|
||||
- (NSString*)menuItemTitleForHistoryItem:(HistoryItem*)inItem
|
||||
{
|
||||
NSString* itemTitle = [inItem title];
|
||||
if ([itemTitle length] == 0)
|
||||
itemTitle = [inItem url];
|
||||
|
||||
return [itemTitle stringByTruncatingTo:kMaxTitleLength at:kTruncateAtMiddle];
|
||||
}
|
||||
|
||||
- (id)initWithTitle:(NSString *)inTitle
|
||||
{
|
||||
if ((self = [super initWithTitle:inTitle])) {
|
||||
mHistoryItemsDirty = YES;
|
||||
[self setupHistoryMenu];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// this should only be called after app launch, when the data source is available
|
||||
- (void)setupHistoryMenu
|
||||
{
|
||||
// set ourselves up to listen for history changes
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(historyChanged:)
|
||||
name:kNotificationNameHistoryDataSourceChanged
|
||||
object:[HistoryMenuDataSourceOwner sharedHistoryDataSource]];
|
||||
|
||||
// register for menu display
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(menuWillDisplay:)
|
||||
name:NSMenuWillDisplayNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[mRootItem release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)setRootHistoryItem:(HistoryItem*)inRootItem
|
||||
{
|
||||
[mRootItem autorelease];
|
||||
mRootItem = [inRootItem retain];
|
||||
}
|
||||
|
||||
- (HistoryItem*)rootItem
|
||||
{
|
||||
return mRootItem;
|
||||
}
|
||||
|
||||
- (void)setNumLeadingItemsToIgnore:(int)inIgnoreItems
|
||||
{
|
||||
mNumIgnoreItems = inIgnoreItems;
|
||||
}
|
||||
|
||||
- (void)setNeedsRebuild:(BOOL)needsRebuild
|
||||
{
|
||||
mHistoryItemsDirty = needsRebuild;
|
||||
}
|
||||
|
||||
- (void)historyChanged:(NSNotification*)inNotification
|
||||
{
|
||||
id rootChangedItem = [[inNotification userInfo] objectForKey:kNotificationHistoryDataSourceChangedUserInfoChangedItem];
|
||||
// We could optimize by only changing single menu items if itemOnlyChanged is true. Normally this will also be a visit
|
||||
// date change, which we can ignore.
|
||||
//BOOL itemOnlyChanged = [[[inNotification userInfo] objectForKey:kNotificationHistoryDataSourceChangedUserInfoChangedItemOnly] boolValue];
|
||||
|
||||
// If rootChangedItem is nil, the whole history tree is being rebuilt.
|
||||
// We need to clear our root item, because it will become invalid. We'll set it again when we rebuild.
|
||||
if (!rootChangedItem) {
|
||||
[self setRootHistoryItem:nil];
|
||||
[self setNeedsRebuild:YES];
|
||||
}
|
||||
else if (mRootItem == rootChangedItem ||
|
||||
[mRootItem isDescendentOfItem:rootChangedItem] ||
|
||||
[rootChangedItem isDescendentOfItem:mRootItem])
|
||||
{
|
||||
[self setNeedsRebuild:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)menuWillDisplay:(NSNotification*)inNotification
|
||||
{
|
||||
if ([self isTargetOfMenuDisplayNotification:[inNotification object]])
|
||||
[self menuWillBeDisplayed];
|
||||
}
|
||||
|
||||
- (void)clearHistoryItems
|
||||
{
|
||||
[self removeItemsFromIndex:0];
|
||||
}
|
||||
|
||||
- (void)rebuildHistoryItems
|
||||
{
|
||||
// remove everything after the "before" item
|
||||
[self clearHistoryItems];
|
||||
|
||||
// now iterate through the history items
|
||||
NSEnumerator* childEnum = [[mRootItem children] objectEnumerator];
|
||||
|
||||
// skip the first mNumIgnoreItems items
|
||||
for (int i = 0; i < mNumIgnoreItems; ++i)
|
||||
[childEnum nextObject];
|
||||
|
||||
int remainingEntriesToShow = kMaxNumHistoryItems;
|
||||
HistoryItem* curChild;
|
||||
while (((curChild = [childEnum nextObject])) && remainingEntriesToShow > 0) {
|
||||
NSMenuItem* newItem = nil;
|
||||
|
||||
if ([curChild isKindOfClass:[HistorySiteItem class]]) {
|
||||
newItem = [[[NSMenuItem alloc] initWithTitle:[self menuItemTitleForHistoryItem:curChild]
|
||||
action:@selector(openHistoryItem:)
|
||||
keyEquivalent:@""] autorelease];
|
||||
[newItem setImage:[curChild iconAllowingLoad:NO]];
|
||||
[newItem setTarget:self];
|
||||
[newItem setRepresentedObject:curChild];
|
||||
|
||||
[self addItem:newItem];
|
||||
[self addCommandKeyAlternatesForMenuItem:newItem];
|
||||
remainingEntriesToShow--;
|
||||
}
|
||||
else if ([curChild isKindOfClass:[HistoryCategoryItem class]] && ([curChild numberOfChildren] > 0)) {
|
||||
NSString* itemTitle = [self menuItemTitleForHistoryItem:curChild];
|
||||
newItem = [[[NSMenuItem alloc] initWithTitle:itemTitle
|
||||
action:nil
|
||||
keyEquivalent:@""] autorelease];
|
||||
[newItem setImage:[curChild iconAllowingLoad:NO]];
|
||||
|
||||
HistorySubmenu* newSubmenu = [[HistorySubmenu alloc] initWithTitle:itemTitle];
|
||||
[newSubmenu setRootHistoryItem:curChild];
|
||||
[newItem setSubmenu:newSubmenu];
|
||||
|
||||
[self addItem:newItem];
|
||||
remainingEntriesToShow--;
|
||||
}
|
||||
}
|
||||
|
||||
[self addLastItems];
|
||||
|
||||
[self setNeedsRebuild:NO];
|
||||
}
|
||||
|
||||
- (void)addLastItems
|
||||
{
|
||||
if (([[[self rootItem] children] count] - mNumIgnoreItems) > (unsigned)kMaxNumHistoryItems) {
|
||||
[self addItem:[NSMenuItem separatorItem]];
|
||||
NSMenuItem* showMoreItem = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"ShowMoreHistoryMenuItem", @"")
|
||||
action:@selector(showHistory:)
|
||||
keyEquivalent:@""] autorelease];
|
||||
[showMoreItem setRepresentedObject:mRootItem];
|
||||
[self addItem:showMoreItem];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)menuWillBeDisplayed
|
||||
{
|
||||
if (mHistoryItemsDirty)
|
||||
[self rebuildHistoryItems];
|
||||
}
|
||||
|
||||
- (BOOL)validateMenuItem:(NSMenuItem*)aMenuItem
|
||||
{
|
||||
BrowserWindowController* browserController = [(MainController *)[NSApp delegate] mainWindowBrowserController];
|
||||
SEL action = [aMenuItem action];
|
||||
|
||||
// disable history if a sheet is up
|
||||
if (action == @selector(openHistoryItem:))
|
||||
return !(browserController && [[browserController window] attachedSheet]);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)openHistoryItem:(id)sender
|
||||
{
|
||||
id repObject = [sender representedObject];
|
||||
if ([repObject isKindOfClass:[HistoryItem class]]) {
|
||||
NSString* itemURL = [repObject url];
|
||||
|
||||
// XXX share this logic with MainController and HistoryOutlineViewDelegate
|
||||
BrowserWindowController* bwc = [(MainController *)[NSApp delegate] mainWindowBrowserController];
|
||||
if (bwc) {
|
||||
if ([sender keyEquivalentModifierMask] & NSCommandKeyMask) {
|
||||
BOOL openInTab = [[PreferenceManager sharedInstance] getBooleanPref:kGeckoPrefOpenTabsForMiddleClick
|
||||
withSuccess:NULL];
|
||||
BOOL backgroundLoad = [BrowserWindowController shouldLoadInBackgroundForDestination:(openInTab ? eDestinationNewTab
|
||||
: eDestinationNewWindow)
|
||||
sender:sender];
|
||||
if (openInTab)
|
||||
[bwc openNewTabWithURL:itemURL referrer:nil loadInBackground:backgroundLoad allowPopups:NO setJumpback:NO];
|
||||
else
|
||||
[bwc openNewWindowWithURL:itemURL referrer:nil loadInBackground:backgroundLoad allowPopups:NO];
|
||||
}
|
||||
else {
|
||||
[bwc loadURL:itemURL];
|
||||
}
|
||||
}
|
||||
else {
|
||||
[(MainController *)[NSApp delegate] openBrowserWindowWithURL:itemURL andReferrer:nil behind:nil allowPopups:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface TopLevelHistoryMenu(Private)
|
||||
|
||||
- (void)appLaunchFinished:(NSNotification*)inNotification;
|
||||
- (NSMenuItem*)todayMenuItem;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TopLevelHistoryMenu
|
||||
|
||||
- (NSString*)menuItemTitleForHistoryItem:(HistoryItem*)inItem
|
||||
{
|
||||
// Give the "Today" menu a different title, since part of it is pulled out
|
||||
// into the top level.
|
||||
if ([inItem respondsToSelector:@selector(isTodayCategory)] &&
|
||||
[(HistoryDateCategoryItem*)inItem isTodayCategory])
|
||||
{
|
||||
return NSLocalizedString(@"TopLevelHistoryMenuEarlierToday", nil);
|
||||
}
|
||||
|
||||
return [super menuItemTitleForHistoryItem:inItem];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[mTodayItem release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[self setNeedsRebuild:YES];
|
||||
|
||||
// listen for app launch completion
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(appLaunchFinished:)
|
||||
name:NSApplicationDidFinishLaunchingNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)appLaunchFinished:(NSNotification*)inNotification
|
||||
{
|
||||
mAppLaunchDone = YES;
|
||||
// setup the history menu after a delay, so that other app launch stuff
|
||||
// finishes first
|
||||
[self performSelector:@selector(setupHistoryMenu) withObject:nil afterDelay:0];
|
||||
}
|
||||
|
||||
- (void)menuWillBeDisplayed
|
||||
{
|
||||
if (mAppLaunchDone) {
|
||||
// the root item is nil at launch, and if the history gets totally rebuilt
|
||||
if (!mRootItem) {
|
||||
HistoryDataSource* dataSource = [HistoryMenuDataSourceOwner sharedHistoryDataSource];
|
||||
[dataSource loadLazily];
|
||||
|
||||
mRootItem = [[dataSource rootItem] retain];
|
||||
}
|
||||
}
|
||||
|
||||
[super menuWillBeDisplayed];
|
||||
}
|
||||
|
||||
- (void)clearHistoryItems
|
||||
{
|
||||
[self removeItemsAfterItem:mItemBeforeHistoryItems];
|
||||
}
|
||||
|
||||
- (void)rebuildHistoryItems
|
||||
{
|
||||
[super rebuildHistoryItems];
|
||||
|
||||
NSMenuItem* todayMenuItem = [self todayMenuItem];
|
||||
[mTodayItem autorelease];
|
||||
mTodayItem = [[(HistorySubmenu*)[todayMenuItem submenu] rootItem] retain];
|
||||
|
||||
// Promote the kMaxTodayItems most recent items into the top-level menu.
|
||||
unsigned int maxItems = std::min(kMaxTodayItems, [[mTodayItem children] count]);
|
||||
if (maxItems > 0) {
|
||||
NSArray* latestHistoryItems = [[mTodayItem children] subarrayWithRange:NSMakeRange(0, maxItems)];
|
||||
int todayMenuIndex = [self indexOfItem:todayMenuItem];
|
||||
|
||||
NSEnumerator* latestItemsEnumerator = [latestHistoryItems objectEnumerator];
|
||||
HistoryItem* historyItem;
|
||||
while ((historyItem = [latestItemsEnumerator nextObject])) {
|
||||
NSMenuItem* menuItem = [[[NSMenuItem alloc] initWithTitle:[self menuItemTitleForHistoryItem:historyItem]
|
||||
action:@selector(openHistoryItem:)
|
||||
keyEquivalent:@""] autorelease];
|
||||
[menuItem setImage:[historyItem iconAllowingLoad:NO]];
|
||||
[menuItem setTarget:self];
|
||||
[menuItem setRepresentedObject:historyItem];
|
||||
|
||||
[self insertItem:menuItem atIndex:(todayMenuIndex++)];
|
||||
todayMenuIndex += [self addCommandKeyAlternatesForMenuItem:menuItem];
|
||||
}
|
||||
|
||||
[self insertItem:[NSMenuItem separatorItem] atIndex:todayMenuIndex];
|
||||
|
||||
// Prevent the "Earlier Today" menu from showing the promoted items,
|
||||
// and remove it if nothing is left.
|
||||
[(HistorySubmenu*)[todayMenuItem submenu] setNumLeadingItemsToIgnore:maxItems];
|
||||
if ([[mTodayItem children] count] <= maxItems) {
|
||||
int todayMenuIndex = [self indexOfItem:todayMenuItem];
|
||||
[self removeItemAtIndex:todayMenuIndex];
|
||||
// If that was the only day folder, we have an extra separator now.
|
||||
if ([[self itemAtIndex:todayMenuIndex] isSeparatorItem])
|
||||
[self removeItemAtIndex:todayMenuIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSMenuItem*)todayMenuItem
|
||||
{
|
||||
NSEnumerator* menuEnumerator = [[self itemArray] objectEnumerator];
|
||||
NSMenuItem* menuItem;
|
||||
while ((menuItem = [menuEnumerator nextObject])) {
|
||||
if ([[menuItem submenu] respondsToSelector:@selector(rootItem)]) {
|
||||
HistoryItem* historyItem = [(HistorySubmenu*)[menuItem submenu] rootItem];
|
||||
if ([historyItem respondsToSelector:@selector(isTodayCategory)] &&
|
||||
[(HistoryDateCategoryItem*)historyItem isTodayCategory])
|
||||
{
|
||||
return menuItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)addLastItems
|
||||
{
|
||||
// at the bottom of the go menu, add a Clear History item
|
||||
if ([[mRootItem children] count] > 0)
|
||||
[self addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
NSMenuItem* clearHistoryItem = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"ClearHistoryMenuItem", @"")
|
||||
action:@selector(clearHistory:)
|
||||
keyEquivalent:@""] autorelease];
|
||||
[self addItem:clearHistoryItem];
|
||||
}
|
||||
|
||||
- (void)historyChanged:(NSNotification*)inNotification
|
||||
{
|
||||
id rootChangedItem = [[inNotification userInfo] objectForKey:kNotificationHistoryDataSourceChangedUserInfoChangedItem];
|
||||
|
||||
// If rootChangedItem is nil, the whole history tree is being rebuilt.
|
||||
if (!rootChangedItem) {
|
||||
[mTodayItem release];
|
||||
mTodayItem = nil;
|
||||
}
|
||||
else if (mTodayItem == rootChangedItem ||
|
||||
mTodayItem == [rootChangedItem parentItem])
|
||||
{
|
||||
[self setNeedsRebuild:YES];
|
||||
}
|
||||
|
||||
[super historyChanged:inNotification];
|
||||
}
|
||||
|
||||
@end
|
Загрузка…
Ссылка в новой задаче