File:  [mozdev] / chimera / BrowserWindowController.mm
Revision 1.54: download - view: text, annotated - select for diffs - revision graph
Sun Mar 17 11:07:14 2002 UTC (15 years, 7 months ago) by macserv
Branches: MAIN
CVS tags: HEAD
This represents my final planned checkin for version 0.2.0 of this project.  BrowserWindowController was modified to allow for a dynamic 'Sidebar' toolbar icon, and the requisite graphics have also been added.  Credits were modified to include a few individual contributors.  A TruncatedTabView object is being created, but is not ready for 0.2.0.  I am adding it to CVS anyway to alleviate the potential for error, but it is not linked.  The sidebar tab icons have been updated, along with the Stop and Reload toolbar icons.

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 *
 * 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 the Initial Developer are Copyright (C) 2002
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * 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 NPL, 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 NPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#import "BrowserWindowController.h"
#import "MyBrowserView.h"
#import "IconTabViewItem.h"

#include "nsIWebNavigation.h"
#include "nsCocoaBrowserService.h"

static NSString *BrowserToolbarIdentifier	= @"Browser Window Toolbar";
static NSString *BackToolbarItemIdentifier	= @"Back Toolbar Item";
static NSString *ForwardToolbarItemIdentifier	= @"Forward Toolbar Item";
static NSString *ReloadToolbarItemIdentifier	= @"Reload Toolbar Item";
static NSString *StopToolbarItemIdentifier	= @"Stop Toolbar Item";
static NSString *HomeToolbarItemIdentifier	= @"Home Toolbar Item";
static NSString *LocationToolbarItemIdentifier	= @"Location Toolbar Item";
static NSString *SidebarToolbarItemIdentifier	= @"Sidebar Toolbar Item";
static NSString *PrintToolbarItemIdentifier	= @"Print Toolbar Item";

@interface BrowserWindowController(Private)
- (void)setupToolbar;
- (void)setupSidebarTabs;
@end

@implementation BrowserWindowController

-(void)enterModalSession
{
    mModalSession = [NSApp beginModalSessionForWindow: [self window]];
    [NSApp runModalSession: mModalSession];
    [NSApp endModalSession: mModalSession];
    mModalSession = nil;
}

-(void)mouseMoved:(NSEvent*)aEvent
{
    if (mMoveReentrant)
        return;
        
    mMoveReentrant = YES;
    NSView* view = [[[self window] contentView] hitTest: [aEvent locationInWindow]];
    [view mouseMoved: aEvent];
    [super mouseMoved: aEvent];
    mMoveReentrant = NO;
}

- (id)initWithWindowNibName:(NSString *)windowNibName
{
    if ( (self = [super initWithWindowNibName:(NSString *)windowNibName]) ) {
        if ( nsCocoaBrowserService::sNumBrowsers == 0 ) {
            [self setShouldCascadeWindows:NO];
        } else {
            [self setShouldCascadeWindows:YES];
        }
        mInitialized = NO;
        mMoveReentrant = NO;
        mShouldAutosave = YES;
    }
    return self;
}

-(void)autosaveWindowFrame
{
  if (mShouldAutosave)
    [[self window] saveFrameUsingName: @"NavigatorWindow"];
}

-(void)disableAutosave
{
  mShouldAutosave = NO;
}

- (void)windowWillClose:(NSNotification *)notification
{
  printf("Window will close notification.\n");
  [mSidebarBookmarksDataSource windowClosing];

  [self autosaveWindowFrame];
  [self autorelease];
}

- (void)dealloc
{
  printf("Browser controller died.\n");

  // Loop over all tabs, and tell them that the window is closed.
  int numTabs = [mTabBrowser numberOfTabViewItems];
  for (int i = 0; i < numTabs; i++) {
    NSTabViewItem* item = [mTabBrowser tabViewItemAtIndex: i];
    [[item view] windowClosed];
  }
  [mSidebarBrowserView windowClosed];

  [mProgress release];
  
  [super dealloc];
}

- (void)windowDidLoad
{
    [super windowDidLoad];

    // Get our saved dimensions.
    [[self window] setFrameUsingName: @"NavigatorWindow"];
    
    if (mModalSession)
      [NSApp stopModal: mModalSession];
      
    mInitialized = YES;
    
    // Retain with a single extra refcount.  This allows the MyBrowserViews
    // to remove the progress meter from its superview without having to 
    // worry about retaining and releasing it.
    [mProgress retain];
    
    [[self window] setAcceptsMouseMovedEvents: YES];
    
    [self setupToolbar];

//  03/03/2002 mlj Changing strategy a bit here.  The addTab: method was
//	duplicating a lot of the code found here.  I have moved it to that method.
//	We now remove the IB tab, then add one of our own.

    [mTabBrowser removeTabViewItem:[mTabBrowser tabViewItemAtIndex:0]];
    [self newTab];
    
    if (mURL) {
      [self loadURL: mURL];
      [mURL release];
    }
    
    [mSidebarDrawer setDelegate: self];

    [self setupSidebarTabs];
}

- (void)drawerWillOpen: (NSNotification*)aNotification
{
    [mSidebarBookmarksDataSource ensureBookmarks];
}

- (void)drawerDidOpen:(NSNotification *)aNotification
{
    // XXXdwh This is temporary.
    [[mSidebarBrowserView getBrowserView] loadURI: [NSURL URLWithString: @"http://tinderbox.mozilla.org/SeaMonkey/panel.html"] flags:NSLoadFlagsNone];
    [mSidebarToolbarItem setImage:[NSImage imageNamed:@"sidebarOpened"]];
}

- (void)drawerDidClose:(NSNotification *)aNotification
{
    // Unload the Gecko web page in "My Panels" to save memory.
    [mSidebarToolbarItem setImage:[NSImage imageNamed:@"sidebarClosed"]];
    [[mSidebarBrowserView getBrowserView] loadURI: [NSURL URLWithString: @"about:blank"] flags:NSLoadFlagsNone];
}

- (void)setupToolbar
{
    NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:BrowserToolbarIdentifier] autorelease];
    
    [toolbar setDisplayMode:NSToolbarDisplayModeDefault];
    [toolbar setAllowsUserCustomization:YES];
    [toolbar setAutosavesConfiguration:YES];
    [toolbar setDelegate:self];
    [[self window] setToolbar:toolbar];
}


- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
{
    return [NSArray arrayWithObjects:	BackToolbarItemIdentifier,
                                        ForwardToolbarItemIdentifier,
                                        ReloadToolbarItemIdentifier,
                                        StopToolbarItemIdentifier,
                                        HomeToolbarItemIdentifier,
                                        LocationToolbarItemIdentifier,
                                        SidebarToolbarItemIdentifier,
                                        PrintToolbarItemIdentifier,
                                        NSToolbarCustomizeToolbarItemIdentifier,
                                        NSToolbarFlexibleSpaceItemIdentifier,
                                        NSToolbarSpaceItemIdentifier,
                                        NSToolbarSeparatorItemIdentifier,
                                        nil];
}

- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar
{
    return [NSArray arrayWithObjects:	BackToolbarItemIdentifier,
                                        ForwardToolbarItemIdentifier,
                                        ReloadToolbarItemIdentifier,
                                        StopToolbarItemIdentifier,
                                        HomeToolbarItemIdentifier,
                                        LocationToolbarItemIdentifier,
                                        SidebarToolbarItemIdentifier,
                                        nil];
}

- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar
      itemForItemIdentifier:(NSString *)itemIdent
  willBeInsertedIntoToolbar:(BOOL)willBeInserted
{
    NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdent] autorelease];
    if ( [itemIdent isEqual:BackToolbarItemIdentifier] ) {
        [toolbarItem setLabel:@"Back"];
        [toolbarItem setPaletteLabel:@"Go Back"];
        [toolbarItem setToolTip:@"Go back one page"];
        [toolbarItem setImage:[NSImage imageNamed:@"back"]];
        [toolbarItem setTarget:self];
        [toolbarItem setAction:@selector(back:)];
    } else if ( [itemIdent isEqual:ForwardToolbarItemIdentifier] ) {
        [toolbarItem setLabel:@"Forward"];
        [toolbarItem setPaletteLabel:@"Go Forward"];
        [toolbarItem setToolTip:@"Go forward one page"];
        [toolbarItem setImage:[NSImage imageNamed:@"forward"]];
        [toolbarItem setTarget:self];
        [toolbarItem setAction:@selector(forward:)];
    } else if ( [itemIdent isEqual:ReloadToolbarItemIdentifier] ) {
        [toolbarItem setLabel:@"Reload"];
        [toolbarItem setPaletteLabel:@"Reload Page"];
        [toolbarItem setToolTip:@"Reload current page"];
        [toolbarItem setImage:[NSImage imageNamed:@"reload"]];
        [toolbarItem setTarget:self];
        [toolbarItem setAction:@selector(reload:)];
    } else if ( [itemIdent isEqual:StopToolbarItemIdentifier] ) {
        [toolbarItem setLabel:@"Stop"];
        [toolbarItem setPaletteLabel:@"Stop Loading"];
        [toolbarItem setToolTip:@"Stop loading this page"];
        [toolbarItem setImage:[NSImage imageNamed:@"stop"]];
        [toolbarItem setTarget:self];
        [toolbarItem setAction:@selector(stop:)];
    } else if ( [itemIdent isEqual:HomeToolbarItemIdentifier] ) {
        [toolbarItem setLabel:@"Home"];
        [toolbarItem setPaletteLabel:@"Go Home"];
        [toolbarItem setToolTip:@"Go to home page"];
        [toolbarItem setImage:[NSImage imageNamed:@"home"]];
        [toolbarItem setTarget:self];
        [toolbarItem setAction:@selector(home:)];
    } else if ( [itemIdent isEqual:SidebarToolbarItemIdentifier] ) {
        [toolbarItem setLabel:@"Sidebar"];
        [toolbarItem setPaletteLabel:@"Toggle Sidebar"];
        [toolbarItem setToolTip:@"Show or hide the Sidebar"];
        [toolbarItem setImage:[NSImage imageNamed:@"sidebarClosed"]];
        [toolbarItem setTarget:self];
        [toolbarItem setAction:@selector(toggleSidebar:)];
        mSidebarToolbarItem = toolbarItem;
    } else if ( [itemIdent isEqual:LocationToolbarItemIdentifier] ) {
        
        NSMenuItem *menuFormRep = [[[NSMenuItem alloc] init] autorelease];
        
        [toolbarItem setLabel:@"Location"];
        [toolbarItem setPaletteLabel:@"Location"];
        [toolbarItem setImage:[NSImage imageNamed:@"Enter a web location."]];
        [toolbarItem setView:mLocationToolbarView];
        [toolbarItem setMinSize:NSMakeSize(128,32)];
        [toolbarItem setMaxSize:NSMakeSize(2560,32)];
        
        [menuFormRep setTarget:self];
        [menuFormRep setAction:@selector(performAppropriateLocationAction)];
        [menuFormRep setTitle:[toolbarItem label]];
        
        [toolbarItem setMenuFormRepresentation:menuFormRep];
        mLocationToolbarItem = toolbarItem;

    } else if ( [itemIdent isEqual:PrintToolbarItemIdentifier] ) {
        [toolbarItem setLabel:@"Print"];
        [toolbarItem setPaletteLabel:@"Print"];
        [toolbarItem setToolTip:@"Print this page"];
        [toolbarItem setImage:[NSImage imageNamed:@"print"]];
        [toolbarItem setTarget:self];
        [toolbarItem setAction:@selector(printDocument)];
    } else {
        toolbarItem = nil;
    }
        
    return toolbarItem;
}

// This method handles the enabling/disabling of the toolbar buttons.
- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem
{
  // Check the action and see if it matches.
  SEL action = [theItem action];
  if (action == @selector(back:))
    return [[mBrowserView getBrowserView] canGoBack];
  else if (action == @selector(forward:))
    return [[mBrowserView getBrowserView] canGoForward];
  else if (action == @selector(reload:))
    return [mBrowserView isBusy] == NO;
  else if (action == @selector(stop:))
    return [mBrowserView isBusy];
  else
    return YES;
}
   
- (void)updateToolbarItems
{
  [[[self window] toolbar] validateVisibleItems];
}

- (void)performAppropriateLocationAction
{
    if ( [[[self window] toolbar] isVisible] ) {
        if ( ([[[self window] toolbar] displayMode] == NSToolbarDisplayModeIconAndLabel) ||
             ([[[self window] toolbar] displayMode] == NSToolbarDisplayModeIconOnly) ) {
            [self focusURLBar];
        } else {
            [self beginLocationSheet];
        }
    } else {
        [self beginLocationSheet];
    }
}

- (void)focusURLBar
{
    [mURLBar selectText: self];
}

- (void)beginLocationSheet
{
    [NSApp beginSheet:	mLocationSheetWindow
       modalForWindow:	[self window]
        modalDelegate:	nil
       didEndSelector:	nil
          contextInfo:	nil];
}

- (IBAction)endLocationSheet:(id)sender
{
    [mLocationSheetWindow orderOut:self];
    [NSApp endSheet:mLocationSheetWindow returnCode:1];
    [self loadURL:[NSURL URLWithString:[mLocationSheetURLField stringValue]]];
    
    // Focus and activate our content area.
    [[mBrowserView getBrowserView] setActive: YES];
}

- (IBAction)goToLocationFromToolbarURLField:(id)sender
{
    [self loadURL:[NSURL URLWithString:[sender stringValue]]];
    
    // Focus and activate our content area.
    [[mBrowserView getBrowserView] setActive: YES];
}

- (void)saveDocument: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList
{
    [[mBrowserView getBrowserView] saveDocument: aFilterView filterList: aFilterList];
}

- (void)printDocument
{
    [[mBrowserView getBrowserView] printDocument];
}

- (void)printPreview
{
    [[mBrowserView getBrowserView] printPreview];
}

- (void)findInPage
{
    [[mBrowserView getBrowserView] findInPage];
}

- (void)findAgain
{
    [[mBrowserView getBrowserView] findAgain];
}

- (void)addBookmark
{
    // XXXdwh Hack.  Just go to the sidebar for now until we get our
    // menu data source going.
    [mSidebarBookmarksDataSource ensureBookmarks];
    [mSidebarBookmarksDataSource addBookmark: self];
}

- (IBAction)back:(id)aSender
{
  [[mBrowserView getBrowserView] goBack];
}

- (IBAction)forward:(id)aSender
{
  [[mBrowserView getBrowserView] goForward];
}

- (IBAction)reload:(id)aSender
{
  [[mBrowserView getBrowserView] reload: 0];
}

- (IBAction)stop:(id)aSender
{
  [[mBrowserView getBrowserView] stop: nsIWebNavigation::STOP_ALL];
}

- (IBAction)home:(id)aSender
{
  [[mBrowserView getBrowserView] loadURI:[NSURL URLWithString:@"about:blank"] flags:NSLoadFlagsNone];
}

- (IBAction)toggleSidebar:(id)aSender
{
    NSResponder* resp = [[self window] firstResponder];
    [[self window] makeFirstResponder: nil];
    
    if ( ([mSidebarDrawer state] == NSDrawerClosedState) || ([mSidebarDrawer state] == NSDrawerClosingState) ) 	{
        // XXXHack to bypass sidebar crashes.
        [mSidebarDrawer open];
    } else {
        [mSidebarDrawer close];
    }
    
    [[self window] makeFirstResponder: resp];
}


-(void)loadURL:(NSURL*)aURL
{
    if (mInitialized) {
        [[mBrowserView getBrowserView] loadURI:aURL flags:NSLoadFlagsNone];
    }
    else {
        mURL = aURL;
        [mURL retain];
    }
}

- (void)updateLocationFields:(NSString *)locationString
{
/* //commenting this out because it doesn't work right yet.
    if ( [locationString length] > 30 ) {
        [[mLocationToolbarItem menuFormRepresentation] setTitle:
            [NSString stringWithFormat:@"Location: %@...", [locationString substringToIndex:31]]];
    } else {
        [[mLocationToolbarItem menuFormRepresentation] setTitle:
            [NSString stringWithFormat:@"Location: %@", locationString]];
    }
*/

    [mURLBar setStringValue:locationString];
    [mLocationSheetURLField setStringValue:locationString];

    [[self window] update];
    [[self window] display];
}

-(void)newTab
{
    NSTabViewItem* newTab = [[[NSTabViewItem alloc] initWithIdentifier: nil] autorelease];
    MyBrowserView* newView = [[[MyBrowserView alloc] initWithFrame: [mBrowserView frame]] autorelease];
    [newView setTab: newTab];

    [newTab setLabel: @"Untitled"];
    [newTab setView: newView];

    [mTabBrowser addTabViewItem: newTab];

    [[newView getBrowserView] loadURI:[NSURL URLWithString:@"about:blank"] flags:NSLoadFlagsNone];

    [mTabBrowser selectLastTabViewItem: self];

    if ( [[[self window] toolbar] isVisible] ) {
        if ( ([[[self window] toolbar] displayMode] == NSToolbarDisplayModeIconAndLabel) ||
             ([[[self window] toolbar] displayMode] == NSToolbarDisplayModeIconOnly) ) {
            [self focusURLBar];
        }
    }
}

-(void)closeTab
{
  if ( [mTabBrowser numberOfTabViewItems] > 1 ) {
    [[[mTabBrowser selectedTabViewItem] view] windowClosed];
    [mTabBrowser removeTabViewItem:[mTabBrowser selectedTabViewItem]];
  }
}

- (void)previousTab
{
    [mTabBrowser selectPreviousTabViewItem:self];
}

- (void)nextTab
{
    [mTabBrowser selectNextTabViewItem:self];
}

- (void)tabView:(NSTabView *)aTabView didSelectTabViewItem:(NSTabViewItem *)aTabViewItem
{
    // Disconnect the old view, if one has been designated.
    // If the window has just been opened, none has been.
    if ( mBrowserView ) {
        [mBrowserView disconnectView];
    }
    // Connect up the new view
    mBrowserView = [aTabViewItem view];
       
    // Make the new view the primary content area.
    [mBrowserView makePrimaryBrowserView: mURLBar status: mStatus
        progress: mProgress windowController: self];
}

-(MyBrowserView*)getMyBrowserView
{
    return mBrowserView;
}

-(void)openNewWindowWithURL: (NSURL*)aURL loadInBackground: (BOOL)aLoadInBG
{
  // Autosave our dimensions before we open a new window.  That ensures the size ends up matching.
  [self autosaveWindowFrame];

  BrowserWindowController* browser = [[BrowserWindowController alloc] initWithWindowNibName: @"BrowserWindow"];
  [browser loadURL: aURL];
  if (aLoadInBG)
    [[browser window] orderWindow: NSWindowBelow relativeTo: [[self window] windowNumber]];
  else
    [browser showWindow: self];

  // XXXdwh Focus the content area.
}

-(void)openNewTabWithURL: (NSURL*)aURL loadInBackground: (BOOL)aLoadInBG
{
    NSTabViewItem* newTab = [[[NSTabViewItem alloc] initWithIdentifier: nil] autorelease];
    
    NSTabViewItem* selectedTab = [mTabBrowser selectedTabViewItem];
    int index = [mTabBrowser indexOfTabViewItem: selectedTab];
    [mTabBrowser insertTabViewItem: newTab atIndex: index+1];
    
    MyBrowserView* newView = [[[MyBrowserView alloc] initWithFrame: [mBrowserView frame]] autorelease];
    [newView setTab: newTab];
    
    [newTab setLabel: @"Loading..."];
    [newTab setView: newView];

    [[newView getBrowserView] loadURI:aURL flags:NSLoadFlagsNone];

    if (!aLoadInBG)
        [mTabBrowser selectTabViewItem: newTab];
        
    // XXXdwh Focus the content area.
}

-(void)setupSidebarTabs
{
    IconTabViewItem   *bookItem = [[IconTabViewItem alloc] initWithIdentifier:@"bookmarkSidebarIconTabViewItem"
                                  withTabIcon:[NSImage imageNamed:@"bookicon"]];
    IconTabViewItem   *histItem = [[IconTabViewItem alloc] initWithIdentifier:@"historySidebarIconTabViewItem"
                                  withTabIcon:[NSImage imageNamed:@"historyicon"]];
    IconTabViewItem *searchItem = [[IconTabViewItem alloc] initWithIdentifier:@"searchSidebarIconTabViewItem"
                                  withTabIcon:[NSImage imageNamed:@"searchicon"]];

    [bookItem   setView:[[mSidebarSourceTabView tabViewItemAtIndex:0] view]];
    [histItem   setView:[[mSidebarSourceTabView tabViewItemAtIndex:1] view]];
    [searchItem setView:[[mSidebarSourceTabView tabViewItemAtIndex:2] view]];

    [mSidebarTabView insertTabViewItem:bookItem   atIndex:0];
    [mSidebarTabView insertTabViewItem:histItem   atIndex:1];
    [mSidebarTabView insertTabViewItem:searchItem atIndex:2];

    [mSidebarTabView selectFirstTabViewItem:self];
}


@end


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>