Compare commits

..

2 Commits

Author SHA1 Message Date
alecf%netscape.com
329176af86 move my changes to the new tag
git-svn-id: svn://10.0.0.236/branches/alecf_treecleanup_branch@52810 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 22:16:18 +00:00
(no author)
ff8acbb81f This commit was manufactured by cvs2svn to create branch
'alecf_treecleanup_branch'.

git-svn-id: svn://10.0.0.236/branches/alecf_treecleanup_branch@52692 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 07:11:46 +00:00
110 changed files with 22812 additions and 9122 deletions

View File

@@ -1,80 +0,0 @@
#!perl
#
# 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 Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Simon Fraser <sfraser@netscape.com>
#
require 5.004;
use strict;
use Cwd;
use Moz::BuildUtils;
use Moz::BuildCore;
#-------------------------------------------------------------
# Where have the build options gone?
#
# The various build flags have been centralized into one place.
# The master list of options is in MozBuildFlags.txt. However,
# you should never need to edit that file, or this one.
#
# To customize what gets built, or where to start the build,
# edit the $prefs_file_name file in
# System Folder:Preferences:Mozilla build prefs:
# Documentation is provided in that file.
#-------------------------------------------------------------
my($prefs_file_name) = "Mozilla opt build prefs";
my($config_header_file_name) = ":mozilla:config:mac:DefinesOptions.h";
#-------------------------------------------------------------
# hashes to hold build options
#-------------------------------------------------------------
my(%build);
my(%options);
my(%filepaths);
my(%optiondefines);
# Hash of input files for this build. Eventually, there will be
# input files for manifests, and projects too.
my(%inputfiles) = (
"buildflags", "MozillaBuildFlags.txt",
"checkoutdata", "MozillaCheckoutList.txt",
"buildprogress", "¥ Mozilla opt progress",
"buildmodule", "MozillaBuildList.pm",
"checkouttime", "Mozilla last checkout"
);
#-------------------------------------------------------------
# end build hashes
#-------------------------------------------------------------
# set the build root directory, which is the the dir above mozilla
SetupBuildRootDir(":mozilla:build:mac:build_scripts");
# Set up all the flags on $main::, like DEBUG, CARBON etc.
# Override the defaults using the preferences files.
SetupDefaultBuildOptions(0, ":mozilla:dist:viewer:", $config_header_file_name);
my($do_checkout) = 0;
my($do_build) = 1;
RunBuild($do_checkout, $do_build, \%inputfiles, $prefs_file_name);

View File

@@ -1,80 +0,0 @@
#!perl
#
# 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 Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Simon Fraser <sfraser@netscape.com>
#
require 5.004;
use strict;
use Cwd;
use Moz::BuildUtils;
use Moz::BuildCore;
#-------------------------------------------------------------
# Where have the build options gone?
#
# The various build flags have been centralized into one place.
# The master list of options is in MozBuildFlags.txt. However,
# you should never need to edit that file, or this one.
#
# To customize what gets built, or where to start the build,
# edit the $prefs_file_name file in
# System Folder:Preferences:Mozilla build prefs:
# Documentation is provided in that file.
#-------------------------------------------------------------
my($prefs_file_name) = "Mozilla debug build prefs";
my($config_header_file_name) = ":mozilla:config:mac:DefinesOptionsDebug.h";
#-------------------------------------------------------------
# hashes to hold build options
#-------------------------------------------------------------
my(%build);
my(%options);
my(%filepaths);
my(%optiondefines);
# Hash of input files for this build. Eventually, there will be
# input files for manifests, and projects too.
my(%inputfiles) = (
"buildflags", "MozillaBuildFlags.txt",
"checkoutdata", "MozillaCheckoutList.txt",
"buildprogress", "¥ Mozilla debug progress",
"buildmodule", "MozillaBuildList.pm",
"checkouttime", "Mozilla last checkout"
);
#-------------------------------------------------------------
# end build hashes
#-------------------------------------------------------------
# set the build root directory, which is the the dir above mozilla
SetupBuildRootDir(":mozilla:build:mac:build_scripts");
# Set up all the flags on $main::, like DEBUG, CARBON etc.
# Override the defaults using the preferences files.
SetupDefaultBuildOptions(1, ":mozilla:dist:viewer_debug:", $config_header_file_name);
my($do_pull) = 0; # overridden by flags and prefs
my($do_build) = 1;
RunBuild($do_pull, $do_build, \%inputfiles, $prefs_file_name);

View File

@@ -1,595 +0,0 @@
#!perl -w
package Moz::BuildCore;
require 5.004;
require Exporter;
use strict;
use vars qw( @ISA @EXPORT );
# perl includes
use Cwd;
use POSIX;
use Time::Local;
use File::Basename;
use LWP::Simple;
# homegrown
use Moz::Moz;
use Moz::Jar;
use Moz::BuildFlags;
use Moz::BuildUtils;
use Moz::CodeWarriorLib;
# use MozillaBuildList; # eventually, this should go away, and be replaced by data input
@ISA = qw(Exporter);
@EXPORT = qw(
RunBuild
);
#//--------------------------------------------------------------------------------------------------
#// DoPrebuildCheck
#//
#// Check the build tools etc before running the build.
#//--------------------------------------------------------------------------------------------------
sub DoPrebuildCheck()
{
SanityCheckBuildOptions();
# launch codewarrior and persist its location. Have to call this before first
# call to getCodeWarriorPath().
my($ide_path_file) = $main::filepaths{"idepath"};
$ide_path_file = full_path_to($ide_path_file);
LaunchCodeWarrior($ide_path_file);
}
#//--------------------------------------------------------------------------------------------------
#// SanityCheckBuildOptions
#//--------------------------------------------------------------------------------------------------
sub SanityCheckBuildOptions()
{
my($bad_options) = 0;
# Jar options
if (!$main::options{chrome_jars} && !$main::options{chrome_files})
{
print "Warning: Both \$options{chrome_jars} and \$options{chrome_files} are off. You won't get any chrome.\n";
$bad_options = 1;
}
if (!$main::options{chrome_jars} && $main::options{use_jars})
{
print "Warning: \$options{chrome_jars} is off but \$options{use_jars} is on. Your build won't run (expects jars, got files).\n";
$bad_options = 1;
}
if (!$main::options{chrome_files} && !$main::options{use_jars})
{
print "Warning: \$options{chrome_jars} is off but \$options{chrome_files} is on. Your build won't run (expects files, got jars).\n";
$bad_options = 1;
}
if ($main::options{ldap_experimental} && !$main::options{ldap})
{
print "Warning: \$options{ldap_experimental} is on but \$options{ldap} is off. LDAP experimental features will not be built.\n";
$bad_options = 1;
}
if ($main::options{wsp} && !$main::options{xmlextras})
{
print "Warning: \$options{wsp} is on but \$options{xmlextras} is off. wsp will not be built.\n";
$bad_options = 1;
}
if ($bad_options) {
print "Build will start in 5 seconds. Press command-. to stop\n";
DelayFor(5);
}
}
#//--------------------------------------------------------------------------------------------------
#// GenBuildSystemInfo
#//--------------------------------------------------------------------------------------------------
sub GenBuildSystemInfo()
{
# always rebuild the configuration program.
BuildProjectClean(":mozilla:build:mac:tools:BuildSystemInfo:BuildSystemInfo.mcp", "BuildSystemInfo");
# delete the configuration file.
unlink(":mozilla:build:mac:BuildSystemInfo.pm");
# run the program.
system(":mozilla:build:mac:BuildSystemInfo");
# wait for the file to be created.
while (!(-e ":mozilla:build:mac:BuildSystemInfo.pm")) { WaitNextEvent(); }
# wait for BuildSystemInfo to finish, so that we see correct results.
while (IsProcessRunning("BuildSystemInfo")) { WaitNextEvent(); }
# now, evaluate the contents of the file.
open(F, ":mozilla:build:mac:BuildSystemInfo.pm");
while (<F>) { eval; }
close(F);
}
#//--------------------------------------------------------------------------------------------------
#// Make library aliases
#//--------------------------------------------------------------------------------------------------
sub MakeLibAliases()
{
my($dist_dir) = GetBinDirectory();
#// ProfilerLib
if ($main::PROFILE)
{
my($profilerlibpath) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:Profiler:Profiler Common:ProfilerLib");
MakeAlias("$profilerlibpath", "$dist_dir"."Essential Files:");
}
}
#//--------------------------------------------------------------------------------------------------
#// ConfigureBuildSystem
#//
#// defines some build-system configuration variables.
#//--------------------------------------------------------------------------------------------------
sub ConfigureBuildSystem()
{
#// In the future, we may want to do configurations based on the actual build system itself.
#// GenBuildSystemInfo();
#// For now, if we discover a newer header file than existed in Universal Interfaces 3.2,
#// we'll assume that 3.3 or later is in use.
my($universal_interfaces) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:Universal:Interfaces:CIncludes:");
if (-e ($universal_interfaces . "ControlDefinitions.h")) {
$main::UNIVERSAL_INTERFACES_VERSION = 0x0330;
}
#// Rename IC SDK folder in the Mac OS Support folder
my($ic_sdk_folder) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:ICProgKit2.0.2");
if( -e $ic_sdk_folder)
{
my($new_ic_folder_name) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:(ICProgKit2.0.2)");
rename ($ic_sdk_folder, $new_ic_folder_name);
# note that CodeWarrior doesn't descend into folders with () the name
print "Mozilla no longer needs the Internet Config SDK to build:\n Renaming the 'ICProgKit2.0.2' folder to '(ICProgKit2.0.2)'\n";
}
printf("UNIVERSAL_INTERFACES_VERSION = 0x%04X\n", $main::UNIVERSAL_INTERFACES_VERSION);
# alias required CodeWarrior libs into the Essential Files folder (only the Profiler lib now)
MakeLibAliases();
}
#//--------------------------------------------------------------------------------------------------
#// CheckOutModule. Takes variable number of args; first two are required
#//--------------------------------------------------------------------------------------------------
sub CheckOutModule($$$$)
{
my($session, $module, $revision, $date) = @_;
my($result) = $session->checkout($module, $revision, $date);
# result of 1 is success
if ($result) { return; }
my($checkout_err) = $session->getLastError();
if ($checkout_err == 708) {
die "Error: Checkout was cancelled.\n";
} elsif ($checkout_err == 911) {
die "Error: CVS session settings are incorrect. Check your password, and the CVS root settings.\n";
} elsif ($checkout_err == 703) {
die "Error: CVS checkout failed. Unknown module, unknown tag, bad username, or other CVS error.\n";
} elsif ($checkout_err == 711) {
print "Checkout of '$module' failed.\n";
}
}
#//--------------------------------------------------------------------------------------------------
#// getScriptFolder
#//--------------------------------------------------------------------------------------------------
sub getScriptFolder()
{
return dirname($0);
}
#//--------------------------------------------------------------------------------------------------
#// getScriptFolder
#//--------------------------------------------------------------------------------------------------
sub get_url_contents($)
{
my($url) = @_;
my($url_contents) = LWP::Simple::get($url);
$url_contents =~ s/\r\n/\n/g; # normalize linebreaks
$url_contents =~ s/\r/\n/g; # normalize linebreaks
return $url_contents;
}
#//--------------------------------------------------------------------------------------------------
#// get_files_from_content
#//--------------------------------------------------------------------------------------------------
sub uniq
{
my $lastval;
grep(($_ ne $lastval, $lastval = $_)[$[], @_);
}
#//--------------------------------------------------------------------------------------------------
#// get_files_from_content
#//--------------------------------------------------------------------------------------------------
sub get_files_from_content($)
{
my($content) = @_;
my(@jscalls) = grep (/return js_file_menu[^{]*/, split(/\n/, $content));
my $i;
for ($i = 0; $i < @jscalls ; $i++)
{
$jscalls[$i] =~ s/.*\(|\).*//g;
my(@callparams) = split(/,/, $jscalls[$i]);
my ($repos, $dir, $file, $rev) = grep(s/['\s]//g, @callparams);
$jscalls[$i] = "$dir/$file";
}
&uniq(sort(@jscalls));
}
#//--------------------------------------------------------------------------------------------------
#// getLastUpdateTime
#//
#// Get the last time we updated. Return 0 on failure
#//--------------------------------------------------------------------------------------------------
sub getLastUpdateTime($)
{
my($timestamp_file) = @_;
my($time_string);
local(*TIMESTAMP_FILE);
unless (open(TIMESTAMP_FILE, "< $timestamp_file")) { return 0; }
while (<TIMESTAMP_FILE>)
{
my($line) = $_;
chomp($line);
# ignore comments and empty lines
if ($line =~ /^\#/ || $line =~ /^\s*$/) {
next;
}
$time_string = $line;
}
# get the epoch seconds
my($last_update_secs) = $time_string;
$last_update_secs =~ s/\s#.+$//;
print "FAST_UPDATE found that you last updated at ".localtime($last_update_secs)."\n";
# how long ago was this, in hours?
my($gm_now) = time();
my($update_hours) = 1 + ceil(($gm_now - $last_update_secs) / (60 * 60));
return $update_hours;
}
#//--------------------------------------------------------------------------------------------------
#// saveCheckoutTimestamp
#//
#// Create a file on disk containing the current time. Param is time(), which is an Epoch seconds
#// (and therefore in GMT).
#//
#//--------------------------------------------------------------------------------------------------
sub saveCheckoutTimestamp($$)
{
my($gm_secs, $timestamp_file) = @_;
local(*TIMESTAMP_FILE);
open(TIMESTAMP_FILE, ">$timestamp_file") || die "Failed to open $timestamp_file\n";
print(TIMESTAMP_FILE "# time of last checkout or update, in GMT. Used by FAST_UPDATE\n");
print(TIMESTAMP_FILE "$gm_secs \# around ".localtime()." local time\n");
close(TIMESTAMP_FILE);
}
#//--------------------------------------------------------------------------------------------------
#// FastUpdate
#//
#// Use Bonsai url data to update only those dirs which have new files
#//
#//--------------------------------------------------------------------------------------------------
sub FastUpdate($$)
{
my($modules, $timestamp_file) = @_; # list of modules to check out
my($num_hours) = getLastUpdateTime($timestamp_file);
if ($num_hours == 0 || $num_hours > 170) {
print "Can't fast_update; last update was too long ago, or never. Doing normal checkout.\n";
return 0;
}
print "Doing fast update, pulling files changed in the last $num_hours hours\n";
my($cvsfile) = AskAndPersistFile($main::filepaths{"sessionpath"});
my($session) = Moz::MacCVS->new( $cvsfile );
unless (defined($session)) { die "Error: Checkout aborted. Cannot create session file: $session" }
# activate MacCVS
ActivateApplication('Mcvs');
my($checkout_start_time) = time();
#print "Time now is $checkout_start_time ($checkout_start_time + 0)\n";
my($this_co);
foreach $this_co (@$modules)
{
my($module, $revision, $date) = ($this_co->[0], $this_co->[1], $this_co->[2]);
# assume that things pulled by date wont change
if ($date ne "") {
print "$module is pulled by date, so ignoring in FastUpdate.\n";
next;
}
my($search_type) = "hours";
my($min_date) = "";
my($max_date) = "";
my($url) = "http://bonsai.mozilla.org/cvsquery.cgi?treeid=default&module=${module}&branch=${revision}&branchtype=match&dir=&file=&filetype=match&who=&whotype=match&sortby=Date&hours=${num_hours}&date=${search_type}&mindate=${min_date}&maxdate=${max_date}&cvsroot=%2Fcvsroot";
if ($revision eq "") {
print "Getting list of checkins to $module from Bonsai...\n";
} else {
print "Getting list of checkins to $module on branch $revision from Bonsai...\n";
}
my(@files) = &get_files_from_content(&get_url_contents($url));
if ($#files > 0)
{
my(@cvs_co_list);
my($co_file);
foreach $co_file (@files)
{
print "Updating $co_file\n";
push(@cvs_co_list, $co_file);
}
my($result) = $session->update($revision, \@cvs_co_list);
# result of 1 is success
if (!$result) { die "Error: Fast update failed\n"; }
} else {
print "No files in this module changed\n";
}
}
saveCheckoutTimestamp($checkout_start_time, $timestamp_file);
return 1;
}
#//--------------------------------------------------------------------------------------------------
#// Checkout
#//--------------------------------------------------------------------------------------------------
sub CheckoutModules($$$)
{
my($modules, $pull_date, $timestamp_file) = @_; # list of modules to check out
my($start_time) = TimeStart();
# assertRightDirectory();
my($cvsfile) = AskAndPersistFile($main::filepaths{"sessionpath"});
my($session) = Moz::MacCVS->new( $cvsfile );
unless (defined($session)) { die "Error: Checkout aborted. Cannot create session file: $session" }
my($checkout_start_time) = time();
# activate MacCVS
ActivateApplication('Mcvs');
my($this_co);
foreach $this_co (@$modules)
{
my($module, $revision, $date) = ($this_co->[0], $this_co->[1], $this_co->[2]);
if ($date eq "") {
$date = $pull_date;
}
CheckOutModule($session, $module, $revision, $date);
# print "Checking out $module with ref $revision, date $date\n";
}
saveCheckoutTimestamp($checkout_start_time, $timestamp_file);
TimeEnd($start_time, "Checkout");
}
#//--------------------------------------------------------------------------------------------------
#// ReadCheckoutModulesFile
#//--------------------------------------------------------------------------------------------------
sub ReadCheckoutModulesFile($$)
{
my($modules_file, $co_list) = @_;
my($checkout_file) = getScriptFolder().":".$modules_file;
local(*CHECKOUT_FILE);
open(CHECKOUT_FILE, "< $checkout_file") || die "Error: failed to open checkout list $checkout_file\n";
while (<CHECKOUT_FILE>)
{
my($line) = $_;
chomp($line);
# ignore comments and empty lines
if ($line =~ /^\#/ || $line =~ /^\s*$/) {
next;
}
my(@cvs_co) = ["", "", ""];
my($module, $revision, $date) = (0, 1, 2);
if ($line =~ /\s*([^#,\s]+)\s*\,\s*([^#,\s]+)\s*\,\s*([^#]+)/)
{
@cvs_co[$module] = $1;
@cvs_co[$revision] = $2;
@cvs_co[$date] = $3;
}
elsif ($line =~ /\s*([^#,\s]+)\s*\,\s*([^#,\s]+)\s*(#.+)?/)
{
@cvs_co[$module] = $1;
@cvs_co[$revision] = $2;
}
elsif ($line =~ /\s*([^#,\s]+)\s*\,\s*,\s*([^#,]+)/)
{
@cvs_co[$module] = $1;
@cvs_co[$date] = $2;
}
elsif ($line =~ /\s*([^#,\s]+)/)
{
@cvs_co[$module] = $1;
}
else
{
die "Error: unrecognized line '$line' in $modules_file\n";
}
# strip surrounding space from date
@cvs_co[$date] =~ s/^\s*|\s*$//g;
# print "Going to check out '@cvs_co[$module]', '@cvs_co[$revision]', '@cvs_co[$date]'\n";
push(@$co_list, \@cvs_co);
}
close(CHECKOUT_FILE);
}
#//--------------------------------------------------------------------------------------------------
#// PullFromCVS
#//--------------------------------------------------------------------------------------------------
sub PullFromCVS($$)
{
unless ( $main::build{pull} ) { return; }
my($modules_file, $timestamp_file) = @_;
StartBuildModule("pull");
my(@cvs_co_list);
ReadCheckoutModulesFile($modules_file, \@cvs_co_list);
if ($main::FAST_UPDATE && $main::options{pull_by_date})
{
die "Error: you can't use FAST_UPDATE if you are pulling by date.\n";
}
my($did_fast_update) = $main::FAST_UPDATE && FastUpdate(\@cvs_co_list, $timestamp_file);
if (!$did_fast_update)
{
my($pull_date) = "";
if ($main::options{pull_by_date})
{
# acceptable CVS date formats are (in local time):
# ISO8601 (e.g. "1972-09-24 20:05") and Internet (e.g. "24 Sep 1972 20:05").
# Perl's localtime() string format also seems to work.
$pull_date = localtime().""; # force string interp.
print "Pulling by date $pull_date\n";
}
CheckoutModules(\@cvs_co_list, $pull_date, $timestamp_file);
}
EndBuildModule("pull");
}
#//--------------------------------------------------------------------------------------------------
#// RunBuild
#//--------------------------------------------------------------------------------------------------
sub RunBuild($$$$)
{
my($do_pull, $do_build, $input_files, $build_prefs) = @_;
InitBuildProgress($input_files->{"buildprogress"});
# if we are pulling, we probably want to do a full build, so clear the build progress
if ($do_pull) {
ClearBuildProgress();
}
# read local prefs, and the build progress file, and set flags to say what to build
SetupBuildParams(\%main::build,
\%main::options,
\%main::optiondefines,
\%main::filepaths,
$input_files->{"buildflags"},
$build_prefs);
# If we were told to pull, make sure we do, overriding prefs etc.
if ($do_pull)
{
$main::build{"pull"} = 1;
}
# transfer this flag
$CodeWarriorLib::CLOSE_PROJECTS_FIRST = $main::CLOSE_PROJECTS_FIRST;
# setup the build log
SetupBuildLog($main::filepaths{"buildlogfilepath"}, $main::USE_TIMESTAMPED_LOGS);
StopForErrors();
if ($main::LOG_TO_FILE) {
RedirectOutputToFile($main::filepaths{"scriptlogfilepath"});
}
# run a pre-build check to see that the tools etc are in order
DoPrebuildCheck();
# do the pull
PullFromCVS($input_files->{"checkoutdata"}, $input_files->{"checkouttime"});
unless ($do_build) { return; }
my($build_start) = TimeStart();
# check the build environment
ConfigureBuildSystem();
# here we load and call methods in the build module indirectly.
# we have to use indirection because the build module can be named
# differently for different builds.
chdir(dirname($0)); # change to the script dir
my($build_module) = $input_files->{"buildmodule"};
# load the build module
require $build_module;
{ # scope for no strict 'refs'
no strict 'refs';
my($package_name) = $build_module;
$package_name =~ s/\.pm$//;
chdir($main::MOZ_SRC);
&{$package_name."::BuildDist"}();
chdir($main::MOZ_SRC);
&{$package_name."::BuildProjects"}();
}
# the build finished, so clear the build progress state
ClearBuildProgress();
TimeEnd($build_start, "Build");
print "Build complete\n";
}
1;

View File

@@ -1,425 +0,0 @@
#!perl -w
package Moz::BuildFlags;
require 5.004;
require Exporter;
# Package that attempts to read a file from the Preferences folder,
# and get build settings out of it
use strict;
use Exporter;
use Cwd;
use File::Basename;
use Moz::Moz;
use Moz::Prefs;
use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(
SetupBuildParams
InitBuildProgress
WriteBuildProgress
ClearBuildProgress
ReadBuildProgress
);
my(@build_flags);
my(@options_flags);
my(@filepath_flags);
my(%arrays_list) = (
"build_flags", \@build_flags,
"options_flags", \@options_flags,
"filepath_flags", \@filepath_flags
);
my($progress_file) = "¥ÊBuild progress";
#-------------------------------------------------------------------------------
# appendArrayFlag
#
# Set a flag in the array
#-------------------------------------------------------------------------------
sub appendArrayFlag(@)
{
my($array_name) = shift;
my($setting) = shift;
my($value) = shift;
my(@optional_values);
foreach (@_) {
push(@optional_values, $_);
}
my(@this_flag) = [$setting, $value, @optional_values];
my($flags_array) = $arrays_list{$array_name};
if ($flags_array)
{
push(@{$flags_array}, @this_flag) || die "Failed to append\n";
}
else
{
die "Error: unknown build flags array $array_name\n";
}
}
#-------------------------------------------------------------------------------
# readFlagsFile
#
# Read the file of build flags from disk. File path is relative to the
# script directory.
#-------------------------------------------------------------------------------
sub readFlagsFile($)
{
my($flags_file) = @_;
my($file_path) = $0;
$file_path =~ s/[^:]+$/$flags_file/;
print "Reading build flags from '$file_path'\n";
local(*FLAGS_FILE);
open(FLAGS_FILE, "< $file_path") || die "Error: failed to open flags file $file_path\n";
my($cur_array) = "";
while(<FLAGS_FILE>)
{
my($line) = $_;
chomp($line);
# ignore comments and empty lines
if ($line =~ /^\#/ || $line =~ /^\s*$/) {
next;
}
# 1-word line, probably array name
if ($line =~ /^([^#\s]+)\s*$/)
{
$cur_array = $1;
next;
}
elsif ($line =~ /^([^#\s]+)\s+\"(.+)\"(\s+#.+)?$/) # quoted option, possible comment
{
my($flag) = $1;
my($setting) = $2;
appendArrayFlag($cur_array, $flag, $setting);
}
elsif ($line =~ /^([^#\s]+)((\s+[^#\s]+)+)(\s+#.+)?$/) # multiple word line, possible comment
{
my($flag) = $1;
appendArrayFlag($cur_array, $flag, split(' ', $2));
}
else
{
die "Error: unknown build flag at '$line'\n";
}
}
close(FLAGS_FILE);
}
#-------------------------------------------------------------------------------
# flagsArrayToHash
#
# Utility routine to migrate flag from a 2D array to a hash, where
# item[n][0] is the hash entry name, and item[n][1] is the hash entry value.
#-------------------------------------------------------------------------------
sub flagsArrayToHash($$)
{
my($src_array, $dest_hash) = @_;
my($item);
foreach $item (@$src_array)
{
$dest_hash->{$item->[0]} = $item->[1];
}
}
#-----------------------------------------------
# printHash
#
# Utility routine to print a hash
#-----------------------------------------------
sub printHash($)
{
my($hash_ref) = @_;
print "Printing hash:\n";
my($key, $value);
while (($key, $value) = each (%$hash_ref))
{
print " $key $value\n";
}
}
#-----------------------------------------------
# printBuildArray
#
# Utility routine to print a 2D array
#-----------------------------------------------
sub printBuildArray($)
{
my($build_array) = @_;
my($entry);
foreach $entry (@$build_array)
{
print "$entry->[0] = $entry->[1]\n";
}
}
#-------------------------------------------------------------------------------
# SetBuildFlags
#-------------------------------------------------------------------------------
sub SetBuildFlags($)
{
my($build) = @_;
flagsArrayToHash(\@build_flags, $build);
}
#-------------------------------------------------------------------------------
# SetBuildOptions
#-------------------------------------------------------------------------------
sub SetBuildOptions($)
{
my($options) = @_;
flagsArrayToHash(\@options_flags, $options);
}
#-------------------------------------------------------------------------------
# SetFilepathFlags
#-------------------------------------------------------------------------------
sub SetFilepathFlags($)
{
my($filepath) = @_;
flagsArrayToHash(\@filepath_flags, $filepath);
}
#-------------------------------------------------------------------------------
# SetOptionDefines
#-------------------------------------------------------------------------------
sub SetOptionDefines($)
{
my($optiondefines) = @_;
foreach my $entry (@options_flags)
{
if (defined($entry->[2])) {
$optiondefines->{$entry->[0]}{$entry->[2]} = 1;
}
}
}
#-------------------------------------------------------------------------------
# PropagateAllFlags
#-------------------------------------------------------------------------------
sub PropagateAllFlags($)
{
my($build_array) = @_;
# if "all" is set, set all the flags to 1
unless ($build_array->[0][0] eq "all") { die "Error: 'all' must come first in the flags array\n"; }
if ($build_array->[0][1] == 1)
{
my($index);
foreach $index (@$build_array)
{
$index->[1] = 1;
}
}
}
#//--------------------------------------------------------------------------------------------------
#// _getBuildProgressFile
#//--------------------------------------------------------------------------------------------------
sub _getBuildProgressFile()
{
return $progress_file;
}
#//--------------------------------------------------------------------------------------------------
#// setBuildProgressStart
#//
#// This automagically sets $build{"all"} to 0
#//--------------------------------------------------------------------------------------------------
sub setBuildProgressStart($$)
{
my($build_array, $name) = @_;
my($index);
foreach $index (@$build_array)
{
$index->[1] = 0;
if ($index->[0] eq $name) {
last;
}
}
print "Building from module after $name, as specified by build progress\n";
}
#//--------------------------------------------------------------------------------------------------
#// InitBuildProgress
#//--------------------------------------------------------------------------------------------------
sub InitBuildProgress($)
{
my($prog_file) = @_;
if ($prog_file ne "") {
$progress_file = full_path_to($prog_file);
print "Writing build progress to $progress_file\n";
}
}
#//--------------------------------------------------------------------------------------------------
#// WriteBuildProgress
#//--------------------------------------------------------------------------------------------------
sub WriteBuildProgress($)
{
my($module_built) = @_;
my($progress_file) = _getBuildProgressFile();
if ($progress_file ne "")
{
open(PROGRESS_FILE, ">>$progress_file") || die "Failed to open $progress_file\n";
print(PROGRESS_FILE "$module_built\n");
close(PROGRESS_FILE);
}
}
#//--------------------------------------------------------------------------------------------------
#// ClearBuildProgress
#//--------------------------------------------------------------------------------------------------
sub ClearBuildProgress()
{
my($progress_file) = _getBuildProgressFile();
if ($progress_file ne "") {
unlink $progress_file;
}
}
#//--------------------------------------------------------------------------------------------------
#// WipeBuildProgress
#//--------------------------------------------------------------------------------------------------
sub WipeBuildProgress()
{
print "Ignoring build progress\n";
ClearBuildProgress();
$progress_file = "";
}
#//--------------------------------------------------------------------------------------------------
#// ReadBuildProgress
#//--------------------------------------------------------------------------------------------------
sub ReadBuildProgress($)
{
my($build_array) = @_;
my($progress_file) = _getBuildProgressFile();
my($last_module);
if (open(PROGRESS_FILE, "< $progress_file"))
{
print "Getting build progress from $progress_file\n";
while (<PROGRESS_FILE>)
{
my($line) = $_;
chomp($line);
$last_module = $line;
}
close(PROGRESS_FILE);
}
if ($last_module)
{
setBuildProgressStart($build_array, $last_module);
}
}
#-------------------------------------------------------------------------------
# clearOldBuildSettings
#-------------------------------------------------------------------------------
sub clearOldBuildSettings($$$$)
{
my($build, $options, $optiondefines, $filepaths) = @_;
# empty the arrays in case we're being called twice
@build_flags = ();
@options_flags = ();
@filepath_flags = ();
# and empty the hashes
%$build = ();
%$options = ();
%$optiondefines = ();
%$filepaths = ();
}
#-------------------------------------------------------------------------------
# SetupBuildParams
#-------------------------------------------------------------------------------
sub SetupBuildParams($$$$$$)
{
my($build, $options, $optiondefines, $filepaths, $flags_file, $prefs_file) = @_;
# Empty the hashes and arrays, to wipe out any stale data.
# Needed because these structures persist across two build scripts
# called using 'do' from a parent script.
clearOldBuildSettings($build, $options, $optiondefines, $filepaths);
# Read from the flags file, which sets up the various arrays
readFlagsFile($flags_file);
# If 'all' is set in the build array, propagate that to all entries
PropagateAllFlags(\@build_flags);
# read the user pref file, that can change values in the array
ReadMozUserPrefs($prefs_file, \@build_flags, \@options_flags, \@filepath_flags);
# If build progress exists, this clears flags in the array up to a certain point
if ($main::USE_BUILD_PROGRESS) {
ReadBuildProgress(\@build_flags);
} else {
WipeBuildProgress();
}
# printBuildArray(\@build_flags);
# printBuildArray(\@options_flags);
SetBuildFlags($build);
SetBuildOptions($options);
SetOptionDefines($optiondefines);
SetFilepathFlags($filepaths);
# printHash($build);
# printHash($options);
}
1;

View File

@@ -1,786 +0,0 @@
package Moz::BuildUtils;
require 5.004;
require Exporter;
# Package that contains build util functions specific to the Mozilla build
# process.
use strict;
use Exporter;
use Cwd;
use File::Path;
use File::Basename;
use Mac::Events;
use Mac::StandardFile;
use Moz::Moz;
use Moz::BuildFlags;
use Moz::MacCVS;
#use Moz::ProjectXML; #optional; required for static build only
use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(
SetupDefaultBuildOptions
SetupBuildRootDir
StartBuildModule
EndBuildModule
GetBinDirectory
BuildOneProjectWithOutput
BuildOneProject
BuildProject
BuildProjectClean
BuildIDLProject
BuildFolderResourceAliases
AskAndPersistFile
DelayFor
TimeStart
TimeEnd
EmptyTree
SetupBuildLog
SetBuildNumber
SetTimeBomb
UpdateConfigHeader
);
#//--------------------------------------------------------------------------------------------------
#// SetupDefaultBuildOptions
#//--------------------------------------------------------------------------------------------------
sub SetupDefaultBuildOptions($$$)
{
my($debug, $bin_dir, $config_header_file_name) = @_;
# Here we set up defaults for the various build flags.
# If you want to override any of these, it's best to do
# so via the relevant preferences file, which lives in
# System Folder:Preferences:Mozilla build prefs:{build prefs file}.
# For the name of the prefs file, see the .pl script that you
# run to start this build. The prefs files are created when
# you run the build, and contain some documentation.
#-------------------------------------------------------------
# configuration variables that globally affect what is built
#-------------------------------------------------------------
$main::DEBUG = $debug;
$main::PROFILE = 0;
$main::RUNTIME = 0; # turn on to just build runtime support and NSPR projects
$main::GC_LEAK_DETECTOR = 0; # turn on to use GC leak detection
$main::MOZILLA_OFFICIAL = 0; # generate build number
$main::LOG_TO_FILE = 0; # write perl output to a file
#-------------------------------------------------------------
# configuration variables that affect the manner of building,
# but possibly affecting the outcome.
#-------------------------------------------------------------
$main::ALIAS_SYM_FILES = $main::DEBUG;
$main::CLOBBER_LIBS = 1; # turn on to clobber existing libs and .xSYM files before
# building each project
# The following two options will delete all dist files (if you have $main::build{dist} turned on),
# but leave the directory structure intact.
$main::CLOBBER_DIST_ALL = 1; # turn on to clobber all aliases/files inside dist (headers/xsym/libs)
$main::CLOBBER_DIST_LIBS = 0; # turn on to clobber only aliases/files for libraries/sym files in dist
$main::CLOBBER_IDL_PROJECTS = 0; # turn on to clobber all IDL projects.
$main::CLOBBER_PROJECTS = 0; # turn on to remove object code from each project before building it
$main::UNIVERSAL_INTERFACES_VERSION = 0x0320;
#-------------------------------------------------------------
# configuration variables that are preferences for the build,
# style and do not affect what is built.
#-------------------------------------------------------------
$main::CLOSE_PROJECTS_FIRST = 0;
# 1 = close then make (for development),
# 0 = make then close (for tinderbox).
$main::USE_TIMESTAMPED_LOGS = 0;
$main::USE_BUILD_PROGRESS = 1; # track build progress for restartable builds
#-------------------------------------------------------------
# END OF CONFIG SWITCHES
#-------------------------------------------------------------
$main::BIN_DIRECTORY = $bin_dir;
$main::DEFINESOPTIONS_FILE = $config_header_file_name;
}
#//--------------------------------------------------------------------------------------------------
#// SetupBuildRootDir
#//--------------------------------------------------------------------------------------------------
sub SetupBuildRootDir($)
{
my($rel_path_to_script) = @_;
my($cur_dir) = cwd();
$cur_dir =~ s/$rel_path_to_script$//;
chdir($cur_dir) || die "Error: failed to set build root directory to '$cur_dir'.\nYou probably need to put 'mozilla' one level down (in a folder).\n";
$main::MOZ_SRC = cwd();
}
#//--------------------------------------------------------------------------------------------------
#// StartBuildModule
#//--------------------------------------------------------------------------------------------------
sub StartBuildModule($)
{
my($module) = @_;
print("---- Start of $module ----\n");
}
#//--------------------------------------------------------------------------------------------------
#// EndBuildModule
#//--------------------------------------------------------------------------------------------------
sub EndBuildModule($)
{
my($module) = @_;
WriteBuildProgress($module);
print("---- End of $module ----\n");
}
#--------------------------------------------------------------------------------------------------
# GetBinDirectory
#--------------------------------------------------------------------------------------------------
sub GetBinDirectory()
{
if ($main::BIN_DIRECTORY eq "") { die "Dist directory not set\n"; }
return $main::BIN_DIRECTORY;
}
#--------------------------------------------------------------------------------------------------
# AskAndPersistFile stores the information about the user pick inside
# the file $session_storage
#--------------------------------------------------------------------------------------------------
sub AskAndPersistFile($)
{
my ($sessionStorage) = @_;
my $cvsfile;
if (( -e $sessionStorage) &&
open( SESSIONFILE, $sessionStorage ))
{
# Read in the path if available
$cvsfile = <SESSIONFILE>;
chomp $cvsfile;
close SESSIONFILE;
if ( ! -e $cvsfile )
{
print STDERR "$cvsfile has disappeared\n";
undef $cvsfile;
}
}
unless (defined ($cvsfile))
{
# make sure that MacPerl is a front process
ActivateApplication('McPL');
MacPerl::Answer("Could not find your MacCVS session file. Please choose one", "OK");
# prompt user for the file name, and store it
my $macFile = StandardGetFile( 0, "McvD");
if ( $macFile->sfGood() )
{
$cvsfile = $macFile->sfFile();
# save the choice if we can
if ( open (SESSIONFILE, ">" . $sessionStorage))
{
printf SESSIONFILE $cvsfile, "\n";
close SESSIONFILE;
}
else
{
print STDERR "Could not open storage file $sessionStorage for saving $cvsfile\n";
}
}
}
return $cvsfile;
}
#--------------------------------------------------------------------------------------------------
# BuildIDLProject
#
#--------------------------------------------------------------------------------------------------
sub BuildIDLProject($$)
{
my ($project_path, $module_name) = @_;
if ($main::CLOBBER_IDL_PROJECTS)
{
my (@suffix_list) = (".mcp", ".xml");
my ($project_name, $project_dir, $suffix) = fileparse($project_path, @suffix_list);
if ($suffix eq "") { die "Error: Project, $project_path must end in .xml or .mcp\n"; }
my($datafolder_path);
if ($suffix eq ".xml")
{
$datafolder_path = $project_dir . "_" . $project_name . " Data:";
}
else {
$datafolder_path = $project_dir . $project_name . " Data:";
}
print STDERR "Deleting IDL data folder: $datafolder_path\n";
EmptyTree($datafolder_path);
}
BuildOneProject($project_path, "headers", 0, 0, 0);
BuildOneProject($project_path, $module_name.".xpt", 1, 0, 1);
}
#--------------------------------------------------------------------------------------------------
# CreateStaticLibTargets
#
#--------------------------------------------------------------------------------------------------
sub CreateXMLStaticLibTargets($)
{
my($xml_path) = @_;
my (@suffix_list) = (".xml");
my ($project_name, $project_dir, $suffix) = fileparse($xml_path, @suffix_list);
if ($suffix eq "") { die "XML munging: $xml_path must end in .xml\n"; }
#sniff the file to see if we need to fix up broken Pro5-exported XML
print "Parsing $xml_path\n";
my $ide_version = Moz::ProjectXML::SniffProjectXMLIDEVersion($xml_path);
if ($ide_version eq "4.0")
{
my $new_file = $project_dir.$project_name."2.xml";
print "Cleaning up Pro 5 xml to $new_file\n";
Moz::ProjectXML::CleanupPro5XML($xml_path, $new_file);
unlink $xml_path;
rename ($new_file, $xml_path);
}
my $doc = Moz::ProjectXML::ParseXMLDocument($xml_path);
my @target_list = Moz::ProjectXML::GetTargetsList($doc);
my $target;
my %target_hash; # for easy lookups below
foreach $target (@target_list) { $target_hash{$target} = 1; }
foreach $target (@target_list)
{
if ($target =~ /(.+).shlb$/) # if this is a shared lib target
{
my $target_base = $1;
my $static_target = $target_base.".o";
# ensure that this does not exist already
if ($target_hash{$static_target}) {
print "Static target $static_target already exists in project. Not making\n";
next;
}
print "Making static target '$static_target' from target '$target'\n";
Moz::ProjectXML::CloneTarget($doc, $target, $static_target);
Moz::ProjectXML::SetAsStaticLibraryTarget($doc, $static_target, $static_target);
}
}
print "Writing XML file to $xml_path\n";
my $temp_path = $project_dir."_".$project_name.".xml";
Moz::ProjectXML::WriteXMLDocument($doc, $temp_path, $ide_version);
Moz::ProjectXML::DisposeXMLDocument($doc);
if (-e $temp_path)
{
unlink $xml_path;
rename ($temp_path, $xml_path);
}
else
{
die "Error: Failed to add new targets to XML project\n";
}
}
#//--------------------------------------------------------------------------------------------------
#// ProcessProjectXML
#//
#// Helper routine to allow for XML pre-processing. This should read in the XML, process it,
#// and replace the original file with the processed version.
#//--------------------------------------------------------------------------------------------------
sub ProcessProjectXML($)
{
my($xml_path) = @_;
# we need to manually load Moz::ProjectXML, becaues not everyone will have the
# required perl modules in their distro.
my($cur_dir) = cwd();
chdir(dirname($0)); # change to the script dir
eval "require Moz::ProjectXML";
if ($@) { die "Error: could not do Project XML munging because you do not have the correct XML modules installed. Error is:\n################\n $@################"; }
chdir($cur_dir);
CreateXMLStaticLibTargets($xml_path);
}
#//--------------------------------------------------------------------------------------------------
#// Build one project, and make the alias. Parameters are project path, target name, shared library
#// name, make shlb alias (boolean), make xSYM alias (boolean), and is component (boolean).
#//--------------------------------------------------------------------------------------------------
sub BuildOneProjectWithOutput($$$$$$)
{
my ($project_path, $target_name, $output_name, $alias_lib, $alias_xSYM, $component) = @_;
unless ($project_path =~ m/^$main::BUILD_ROOT.+/) { return; }
my (@suffix_list) = (".mcp", ".xml");
my ($project_name, $project_dir, $suffix) = fileparse($project_path, @suffix_list);
if ($suffix eq "") { die "Error: Project, $project_path must end in .xml or .mcp\n"; }
my($dist_dir) = GetBinDirectory();
# Put libraries in "Essential Files" folder, Components in "Components" folder
my($output_dir) = $component ? "Components:" : "Essential Files:";
my($output_path) = $dist_dir.$output_dir;
if ($main::options{static_build})
{
if ($output_name =~ /\.o$/ || $output_name =~ /\.[Ll]ib$/)
{
$alias_xSYM = 0;
$alias_lib = 1;
$output_path = $main::DEBUG ? ":mozilla:dist:static_libs_debug:" : ":mozilla:dist:static_libs:";
}
}
# if the flag is on to export projects to XML, export and munge them
if ($main::EXPORT_PROJECTS && !($project_path =~ /IDL\.mcp$/))
{
my $xml_out_path = $project_path;
$xml_out_path =~ s/\.mcp$/\.xml/;
# only do this if project is newer?
if (! -e $xml_out_path)
{
ExportProjectToXML(full_path_to($project_path), full_path_to($xml_out_path));
ProcessProjectXML($xml_out_path);
}
}
# if the flag is set to use XML projects, default to XML if the file
# is present.
if ($main::USE_XML_PROJECTS && !($project_path =~ /IDL\.mcp$/))
{
my $xml_project_path = $project_dir.$project_name.".xml";
if (-e $xml_project_path)
{
$project_path = $xml_project_path;
$suffix = ".xml";
}
}
if ($suffix eq ".xml")
{
my($xml_path) = $project_path;
# Prepend an "_" onto the name of the generated project file so it doesn't conflict
$project_path = $project_dir . "_" . $project_name . ".mcp";
my($project_modtime) = (-e $project_path ? GetFileModDate($project_path) : 0);
my($xml_modtime) = (-e $xml_path ? GetFileModDate($xml_path) : 0);
if ($xml_modtime > $project_modtime)
{
print("Importing $project_path from $project_name.xml.\n");
unlink($project_path);
# Might want to delete the "xxx.mcp Data" dir ???
ImportXMLProject(full_path_to($xml_path), full_path_to($project_path));
}
}
if ($main::CLOBBER_LIBS)
{
unlink "$project_dir$output_name"; # it's OK if these fail
unlink "$project_dir$output_name.xSYM";
}
DoBuildProject($project_path, $target_name, $main::CLOBBER_PROJECTS);
$alias_lib ? MakeAlias("$project_dir$output_name", "$output_path") : 0;
$alias_xSYM ? MakeAlias("$project_dir$output_name.xSYM", "$output_path") : 0;
}
#//--------------------------------------------------------------------------------------------------
#// For compatiblity with existing scripts, BuildOneProject now just calls
#// BuildOneProjectWithOutput, with the output name and target name identical.
#// Note that this routine assumes that the target name and the shared libary name
#// are the same.
#//--------------------------------------------------------------------------------------------------
sub BuildOneProject($$$$$)
{
my ($project_path, $target_name, $alias_lib, $alias_xSYM, $component) = @_;
BuildOneProjectWithOutput($project_path, $target_name, $target_name,
$alias_lib, $alias_xSYM, $component);
}
#//--------------------------------------------------------------------------------------------------
#// For compatiblity with existing scripts, BuildProject now just calls
#// BuildOneProjectWithOutput, with the output name and target name identical.
#// Note that this routine assumes that the target name and the shared libary name
#// are the same. No aliases of the output are made.
#//--------------------------------------------------------------------------------------------------
sub BuildProject($$)
{
my ($project_path, $target_name) = @_;
BuildOneProjectWithOutput($project_path, $target_name, $target_name, 0, 0, 0);
}
#//--------------------------------------------------------------------------------------------------
#// Identical to BuildProject but clobbers the project before building it.
#//--------------------------------------------------------------------------------------------------
sub BuildProjectClean($$)
{
my ($project_path, $target_name) = @_;
my ($save_clobber_flag) = $main::CLOBBER_PROJECTS;
$main::CLOBBER_PROJECTS = 1;
BuildOneProjectWithOutput($project_path, $target_name, $target_name, 0, 0, 0);
$main::CLOBBER_PROJECTS = $save_clobber_flag;
}
#//--------------------------------------------------------------------------------------------------
#// Make resource aliases for one directory
#//--------------------------------------------------------------------------------------------------
sub BuildFolderResourceAliases($$)
{
my($src_dir, $dest_dir) = @_;
# get a list of all the resource files
opendir(SRCDIR, $src_dir) || die("can't open $src_dir");
my(@resource_files) = readdir(SRCDIR);
closedir(SRCDIR);
# make aliases for each one into the dest directory
print("Placing aliases to all files from $src_dir in $dest_dir\n");
for ( @resource_files )
{
next if $_ eq "CVS";
#print(" Doing $_\n");
if (-l $src_dir.$_)
{
print(" $_ is an alias\n");
next;
}
my($file_name) = $src_dir . $_;
MakeAlias($file_name, $dest_dir);
}
}
#//--------------------------------------------------------------------------------------------------
#// DelayFor
#//
#// Delay for the given number of seconds, allowing the script to be cancelled
#//--------------------------------------------------------------------------------------------------
sub DelayFor($)
{
my($delay_secs) = @_;
STDOUT->autoflush(1);
my($end_time) = time() + $delay_secs;
my($last_time) = 0;
my($cur_time) = time();
while ($cur_time < $end_time)
{
$cur_time = time();
if ($cur_time > $last_time)
{
print ".";
$last_time = $cur_time;
}
WaitNextEvent();
}
print "\n";
STDOUT->autoflush(0);
}
#//--------------------------------------------------------------------------------------------------
#// TimeStart
#//--------------------------------------------------------------------------------------------------
sub TimeStart()
{
return time();
}
#//--------------------------------------------------------------------------------------------------
#// TimeEnd
#//--------------------------------------------------------------------------------------------------
sub TimeEnd($$)
{
use integer;
my($start_time, $operation_name) = @_;
my($end_time) = time();
my($tot_sec) = $end_time - $start_time;
my($seconds) = $tot_sec;
my($hours) = $seconds / (60 * 60);
$seconds -= $hours * (60 * 60);
my($minutes) = $seconds / 60;
$seconds -= $minutes * 60;
print "$operation_name took $hours hours $minutes minutes and $seconds seconds\n";
}
#//--------------------------------------------------------------------------------------------------
#// Remove all files from a tree, leaving directories intact (except "CVS").
#//--------------------------------------------------------------------------------------------------
sub EmptyTree($)
{
my ($root) = @_;
#print "EmptyTree($root)\n";
opendir(DIR, $root);
my $sub;
foreach $sub (readdir(DIR))
{
my $fullpathname = $root.$sub; # -f, -d only work on full paths
# Don't call empty tree for the alias of a directory.
# -d returns true for the alias of a directory, false for a broken alias)
if (-d $fullpathname)
{
if (-l $fullpathname) # delete aliases
{
unlink $fullpathname;
next;
}
EmptyTree($fullpathname.":");
if ($sub eq "CVS")
{
#print "rmdir $fullpathname\n";
rmdir $fullpathname;
}
}
else
{
unless (unlink $fullpathname) { die "Failed to delete $fullpathname\n"; }
}
}
closedir(DIR);
}
#//--------------------------------------------------------------------------------------------------
#// Recurse through a directory hierarchy, looking for MANIFEST files.
#// Currently unused.
#//--------------------------------------------------------------------------------------------------
sub ScanForManifestFiles($$$$)
{
my($dir, $theme_root, $theme_name, $dist_dir) = @_;
opendir(DIR, $dir) or die "Cannot open dir $dir\n";
my @files = readdir(DIR);
closedir DIR;
my $file;
foreach $file (@files)
{
my $filepath = $dir.":".$file;
if (-d $filepath)
{
# print "Looking for MANIFEST files in $filepath\n";
ScanForManifestFiles($filepath, $theme_root, $theme_name, $dist_dir);
}
elsif ($file eq "MANIFEST")
{
# print "Doing manifest file $filepath\n";
# Get the dest path from the first line of the file
open(MANIFEST, $filepath) || die "Could not open file $file";
# Read in the path if available
my($dest_line) = <MANIFEST>;
chomp $dest_line;
close MANIFEST;
$dest_line =~ s|^#!dest[\t ]+|| || die "No destination line found in $filepath\n";
my($dest_path) = $dist_dir."chrome:skins:$theme_name:$dest_line";
# print " Destination is $dest_path\n";
InstallResources($filepath, "$dest_path", 0);
}
}
}
#-----------------------------------------------
# SetupBuildLog
#-----------------------------------------------
sub SetupBuildLog($$)
{
my($logfile_path, $timestamped_log) = @_;
my($logdir) = "";
my($logfile) = $logfile_path;
if ($logfile_path =~ /(.+?:)([^:]+)$/) # ? for non-greedy match
{
$logdir = $1;
$logfile = $2;
mkpath($logdir);
}
if ($timestamped_log)
{
#Use time-stamped names so that you don't clobber your previous log file!
my $now = localtime();
while ($now =~ s@:@.@) {} # replace all colons by periods
OpenErrorLog("${logdir}${now}");
}
else
{
OpenErrorLog("${logdir}${logfile}");
}
}
#-----------------------------------------------
# SetBuildNumber
#-----------------------------------------------
sub SetBuildNumber($$)
{
my($build_num_file, $files_to_touch) = @_;
# Make sure we add the config dir to search, to pick up mozBDate.pm
# Need to do this dynamically, because this module can be used before
# mozilla/config has been checked out.
my ($inc_path) = $0; # $0 is the path to the parent script
$inc_path =~ s/:build:mac:build_scripts:.+$/:config/;
push(@INC, $inc_path);
require mozBDate;
mozBDate::UpdateBuildNumber($build_num_file, $main::MOZILLA_OFFICIAL);
my($file);
foreach $file (@$files_to_touch)
{
print "Writing build number to $file from ${file}.in\n";
mozBDate::SubstituteBuildNumber($file, $build_num_file, "${file}.in");
}
}
#-----------------------------------------------
# SetTimeBomb
#-----------------------------------------------
sub SetTimeBomb($$)
{
my ($warn_days, $bomb_days) = @_;
system("perl :mozilla:config:mac-set-timebomb.pl $warn_days $bomb_days");
}
#//--------------------------------------------------------------------------------------------------
#// Regenerate a configuration header file if necessary
#//--------------------------------------------------------------------------------------------------
sub UpdateConfigHeader($)
{
my($config_path) = @_;
my($config, $oldconfig) = ("", "");
my($define, $definevalue, $defines);
my($k, $l,);
foreach $k (keys(%main::options))
{
if ($main::options{$k})
{
foreach $l (keys(%{$main::optiondefines{$k}}))
{
$my::defines{$l} = $main::optiondefines{$k}{$l};
print "Setting up my::defines{$l}\n";
}
}
}
my $config_headerfile = current_directory().$config_path;
if (-e $config_headerfile)
{
open(CONFIG_HEADER, "< $config_headerfile") || die "$config_headerfile: $!\n";
my($line);
while ($line = <CONFIG_HEADER>)
{
if ($line =~ m/#define\s+([^\s]*)\s+([^\s]*)\s*\n/)
{
$define = $1;
$definevalue = $2;
#canonicalize so that whitespace changes are not significant
my $canon_value = "#define " . $define . " " . $definevalue . "\n";
$oldconfig .= $canon_value;
if (exists ($my::defines{$define}) and ($my::defines{$define} == $definevalue))
{
delete $my::defines{$define};
$config .= $canon_value;
}
}
}
close(CONFIG_HEADER);
}
if (%my::defines)
{
foreach $k (keys(%my::defines))
{
$config .= "#define " . $k . " " . $my::defines{$k} . "\n";
}
}
my $file_name = basename($config_headerfile);
if (($config ne $oldconfig) || (!-e $config_headerfile))
{
printf("Writing new configuration header $file_name\n");
open(CONFIG_HEADER, "> $config_headerfile") || die "$config_headerfile: $!\n";
print(CONFIG_HEADER "/* This file is auto-generated based on build options. Do not edit. */\n");
print CONFIG_HEADER ($config);
close(CONFIG_HEADER);
MacPerl::SetFileInfo("CWIE", "TEXT", $config_headerfile);
}
else
{
printf("Configuration header $file_name is up-to-date\n");
}
}
1;

View File

@@ -1,660 +0,0 @@
#!perl
package Moz::CodeWarriorLib;
=pod
=head1 NAME
CodeWarriorLib - supply interface to CodeWarrior
=head1 SYNOPSIS
#!perl
use CodeWarriorLib;
CodeWarriorLib::activate();
$had_errors = CodeWarriorLib::build_project(
$project_path, $target_name, $recent_errors_file, $clean_build
);
=head1 DESCRIPTION
Replaces the AppleScript library I<CodeWarriorLib>.
=over 4
=cut
use strict;
use Cwd;
use File::Basename;
use Mac::Types;
use Mac::Events;
use Mac::AppleEvents;
use Mac::AppleEvents::Simple;
use Mac::Processes;
use Mac::MoreFiles;
use Mac::StandardFile;
use vars qw($VERSION);
$VERSION = '1.02';
my($app) = 'CWIE';
my($scriptDir) = cwd(); # could use $0 for this
my($ide_loc_file) = "";
# 0 == don't switch CWIE to front app in do_event(), 1 == do switch
# note: activate() still switches when called
$Mac::AppleEvents::Simple::SWITCH = 0;
# $Mac::AppleEvents::Simple::WARN = 1;
# supply your own path to the source here
#_test('PowerPudgeIV:mozilla:mozilla:');
# If you want to understand the gobbldeygook that's used to build Apple Events,
# you should start by reading the AEGizmos documentation.
=pod
=item _get_project($full_path)
A private routine returning a reference to the open project with the given name,
or else the empty string (when that project is not open)
full_path is a string identifying the project to be built and is of the form,
e.g., "HD:ProjectFolder:MyProject.mcp". It must be supplied.
=cut
sub _get_project ($) {
my(
$full_path, $candidate_projects
) = @_;
$candidate_projects = _doc_named(basename($full_path, '*'));
if ($candidate_projects) {
my($cps) = _get_dobj($candidate_projects);
my($num) = AECountItems($cps);
if ($num) { # is a list
foreach (1 .. AECountItems($cps)) {
my($cp) = AEGetNthDesc($cps, $_);
if (lc $full_path eq lc _full_path($cp)) {
return($cp);
}
}
} else { # is only one, not a list
if (lc $full_path eq lc _full_path($cps)) {
return($cps);
}
}
}
return;
}
=pod
=item build_project
Build a selected target of a project, saving any errors to a file, if supplied.
full_path is a string identifying the project to be built and is of the form,
e.g., "HD:ProjectFolder:MyProject.mcp". It must be supplied.
If target_name is the empty string, the current target of the selected project
will be built, else, target_name should be a string matching a target name in
the selected project.
If error_path is the empty string, errors will not be saved to a file,
else, error_path should be the full path of a file to save error messages into.
=cut
$CodeWarriorLib::CLOSE_PROJECTS_FIRST = 0; # If true we close then make. If false, make then close.
my $last_project_built = "";
my $last_project_was_closed = 0;
sub build_project ($;$$$) {
my(
$full_path, $target_name, $error_path,
$remove_object, $p, $project_was_closed, $had_errors
) = @_;
_close_errors_window();
if ($CodeWarriorLib::CLOSE_PROJECTS_FIRST && ($last_project_built ne $full_path))
{
# If we're in "close first" mode, we don't close if the current project
# is the same as the previous one.
if ($last_project_was_closed) {
$p = _get_project($last_project_built);
_close($p);
}
$last_project_built = $full_path;
$last_project_was_closed = 0; # now refers to the new project
}
$project_was_closed = 0;
while (1) {
$p = _get_project($full_path);
if (!$p) {
if ($project_was_closed) {
print "### Error - request for project document failed after opening\n";
die "### possibly CW Pro 4 bug: be sure to close your Find window\n";
}
$project_was_closed = 1;
$last_project_was_closed = 1;
_open_file($full_path);
} else {
last;
}
}
$had_errors = 0;
if ($target_name eq '') {
if ($remove_object) {_remove_object($p)}
_build($p);
} else {
if ($remove_object) {_remove_object($p, $target_name)}
_build($p, $target_name);
}
if ($error_path ne '') {
_save_errors_window($error_path);
}
$had_errors = _close_errors_window();
if (!$CodeWarriorLib::CLOSE_PROJECTS_FIRST)
{
if ($project_was_closed) {
$p = _get_project($full_path);
_close($p);
}
}
return($had_errors);
}
=pod
=item appIsRunning()
=cut
sub _appIsRunning($)
{
my ($appSignature) = @_;
my ($psi);
my ($found) = 0;
my ($appPSN);
foreach $psi (values(%Process))
{
if ($psi->processSignature() eq $appSignature)
{
$appPSN = $psi->processNumber();
$found = 1;
last;
}
}
return $found;
}
=pod
=item appIsFrontmost()
=cut
sub _appIsFrontmost($)
{
my ($appSignature) = @_;
my ($psi);
my ($found) = 0;
my ($appPSN);
foreach $psi (values(%Process))
{
if ($psi->processSignature() eq $appSignature)
{
$appPSN = $psi->processNumber();
$found = 1;
last;
}
}
return (GetFrontProcess() == $appPSN);
}
=pod
=item activate()
Launches CodeWarrior and brings it to the front.
Once found, path will be saved in $idepath_file for future reference.
Edit or delete this file to change the location of the IDE. If app is
moved, C<activate()> will prompt for a new location.
First looks for an open CodeWarrior app. Second, tries to open previously
saved location in ':idepath.txt'. Third, tries to find it and allow user
to choose it with Navigation Services (if present). Fourth, uses good old
GUSI routines built-in to MacPerl for a Choose Directory dialog box.
=cut
sub activate ($) {
$ide_loc_file = $_[0]; # save in global
my($filepath, $appath, $psi) = ($ide_loc_file);
foreach $psi (values(%Process)) {
if ($psi->processSignature() eq $app) {
$appath = $psi->processAppSpec();
_save_appath($filepath, $appath);
last;
}
}
if (!$appath || !-x $appath) {
$appath = _read_appath($filepath);
}
if (!$appath || ! -x $appath)
{
# make sure that MacPerl is a front process
#ActivateApplication('McPL');
MacPerl::Answer("Please locate the CodeWarrior application.", "OK");
# prompt user for the file name, and store it
my $macFile = StandardGetFile( 0, "APPL");
if ( $macFile->sfGood() )
{
$appath = $macFile->sfFile();
}
else
{
die "Operation canceled\n";
}
# if (eval {require Mac::Navigation}) {
# my($options, $nav);
# Mac::Navigation->import();
# $options = NavGetDefaultDialogOptions();
# $options->message('Where is CodeWarrior IDE?');
# $options->windowTitle('Find CodeWarrior IDE');
# $nav = NavChooseObject($Application{$app}, $options);
# die "CodeWarrior IDE not found.\n" if (!$nav || !$nav->file(1));
# $appath = $nav->file(1);
# } else {
# local(*D);
# my $cwd = `pwd`;
# $appath = _get_folder(
# 'Where is the CW IDE folder?',
# dirname($Application{$app})
# );
# die "CodeWarrior IDE not found.\n" if !$appath;
# opendir(D, $appath) or die $!;
# chdir($appath);
# foreach my $file (sort readdir (D)) {
# my(@app) = MacPerl::GetFileInfo($file);
# if ($app[0] && $app[1] &&
# $app[1] eq 'APPL' && $app[0] eq $app
# ) {
# $appath .= $file;
# last;
# }
# }
# chomp($cwd);
# chdir($cwd);
# }
_save_appath($filepath, $appath);
}
my($lp) = LaunchParam->new(
launchAppSpec => $appath,
launchControlFlags => launchContinue() + launchNoFileFlags()
);
unless (LaunchApplication($lp)) {
unlink($filepath);
die $^E;
}
# wait for CodeWarrior to show up in the list of processes
while (!_appIsRunning('CWIE'))
{
WaitNextEvent();
}
# wait for CodeWarrior to come to the front
while (!_appIsFrontmost('CWIE'))
{
WaitNextEvent();
}
}
=pod
=item getCodeWarriorPath()
Returns a file path relative to the CodeWarrior folder
=cut
sub getCodeWarriorPath($)
{
my($subfolder)=@_;
my($app_path) = _read_appath($ide_loc_file);
if ($app_path eq "") { die "Error: Failed to get CodeWarrior IDE path\n"; }
my($codewarrior_root) = $app_path;
$codewarrior_root =~ s/[^:]*$//;
return ($codewarrior_root . $subfolder);
}
=pod
=item getCodeWarriorIDEName()
Returns the name of the CodeWarrior application
=cut
sub getCodeWarriorIDEName()
{
my($subfolder)=@_;
my($app_path) = _read_appath($ide_loc_file);
if ($app_path eq "") { die "Error: Failed to get CodeWarrior IDE path\n"; }
my(@codewarrior_path) = split(/:/, $app_path);
return pop(@codewarrior_path);
}
=pod
=item quit()
Quits CodeWarrior.
=cut
sub quit() {
$last_project_built = "";
$last_project_was_closed = 0;
my($evt) = do_event(qw/aevt quit/, $app);
}
sub _build ($;$) {
my($evt);
if ($_[1]) {
my($prm) =
q"'----':obj {form:name, want:type(TRGT), seld:TEXT(@), from:" .
AEPrint($_[0]) . '}';
$evt = do_event(qw/CWIE MAKE/, $app, $prm, $_[1]);
} else {
my($prm) = q"'----':" . AEPrint($_[0]);
$evt = do_event(qw/CWIE MAKE/, $app, $prm);
}
}
sub _remove_object ($;$) {
my($evt);
if ($_[1]) {
my($prm) =
q"'----':obj {form:name, want:type(TRGT), seld:TEXT(@), from:" .
AEPrint($_[0]) . '}';
$evt = do_event(qw/CWIE RMOB/, $app, $prm, $_[1]);
} else {
my($prm) = q"'----':" . AEPrint($_[0]);
$evt = do_event(qw/CWIE RMOB/, $app, $prm);
}
}
sub _open_file ($) {
my($prm) =
q"'----':obj {form:name, want:type(alis), " .
q"seld:TEXT(@), from:'null'()}";
do_event(qw/aevt odoc/, $app, $prm, $_[0]);
}
sub import_project ($$) {
my($xml_file, $project_path) = @_;
my($prm) = "kocl:type(PRJD), rtyp:TEXT(@), data:TEXT(@), &subj:'null'()";
my($evt) = do_event(qw/core crel/, $app, $prm, $project_path, $xml_file);
my($result) = _get_event_result($evt);
if ($result eq "") {
_close(_get_project($project_path));
}
return $result;
}
sub export_project ($$) {
my($project_path, $xml_out_path) = @_;
my($p, $project_was_closed);
$project_was_closed = 0;
while (1) {
$p = _get_project($project_path);
if (!$p) {
if ($project_was_closed) {
print "### Error - request for project document failed after opening\n";
die "### possibly CW bug: be sure to close your Find window\n";
}
$project_was_closed = 1;
_open_file($project_path);
} else {
last;
}
}
# avoid problems with the Project Messages window
_close_named_window("Project Messages");
my($prm) =
q"'----':obj {form:indx, want:type(PRJD), " .
q"seld:1, from:'null'()}, kfil:TEXT(@)";
my($evt) = do_event(qw/CWIE EXPT/, $app, $prm, $xml_out_path);
if ($project_was_closed) {
$p = _get_project($project_path);
_close($p);
}
return _get_event_result($evt);
}
sub _doc_named ($) {
my($prm) =
q"'----':obj {form:test, want:type(docu), from:'null'(), " .
q"seld:cmpd{relo:'= ', 'obj1':obj {form:prop, want:type" .
q"(prop), seld:type(pnam), from:'exmn'()}, 'obj2':TEXT(@)}}";
my($evt) = do_event(qw/core getd/, $app, $prm, $_[0]);
return($evt->{REPLY} eq 'aevt\ansr{}' ? undef : $evt);
}
sub _full_path ($) {
my($obj) = $_[0];
my($prm) =
q"'----':obj {form:prop, want:type(prop), seld:type(FILE), " .
q"from:" . AEPrint($_[0]) . q"}, rtyp:type(TEXT)";
my($evt) = do_event(qw/core getd/, $app, $prm);
return MacPerl::MakePath(
MacUnpack('fss ', (
AEGetParamDesc($evt->{REP}, keyDirectObject()))->data()->get()
)
);
}
sub _save_errors_window ($) {
my($prm) =
q"'----':obj {form:name, want:type(alis), seld:TEXT(@), from:'null'()}";
do_event(qw/MMPR SvMs/, $app, $prm, $_[0]);
}
sub _close_errors_window () {
return _close_named_window('Errors & Warnings');
}
sub _close_named_window ($) {
my($window_name) = @_;
my($prm) =
q"'----':obj {form:name, want:type(cwin), " .
q"seld:TEXT(@), from:'null'()}";
my($evt) = do_event(qw/core clos/, $app, $prm, $window_name);
return($evt->{REPLY} eq 'aevt\ansr{}' ? 1 : 0);
}
sub _close () {
my($prm) = q"'----':" . AEPrint($_[0]);
do_event(qw/core clos/, $app, $prm);
}
sub _get_dobj ($) {
return(AEGetParamDesc($_[0]->{REP}, keyDirectObject()));
}
sub _get_folder ($$) {
require 'GUSI.ph';
my($prompt, $default) = @_;
MacPerl::Choose(
GUSI::AF_FILE(), 0, $prompt, '',
GUSI::CHOOSE_DIR() + ($default ? &GUSI::CHOOSE_DEFAULT : 0),
$default
);
}
sub _get_event_result ($)
{
my($evt) = @_;
my($result) = $evt->{ERROR};
if ( $result eq "" && $evt->{ERRNO} != 0 )
{
$result = "unknown error (".$evt->{ERRNO}.")";
}
return $result;
}
sub _save_appath ($$) {
my($cwd) = cwd(); # remember the current working dir
chdir($scriptDir); # change dir to the script dir
local(*F);
open(F, '>' . $_[0]) or die $!;
print F $_[1];
close(F);
chdir($cwd); # restore the cwd
}
sub _read_appath ($) {
my($filepath) = @_;
my($cwd) = cwd(); # remember the current working dir
chdir($scriptDir); # change dir to the script dir
if (! -e $filepath) {
return "";
}
local(*F);
open(F, $filepath);
my($appath) = <F>;
close(F);
chdir($cwd); # restore the cwd
return($appath);
}
sub _test ($) {
activate($ide_loc_file);
my($path) = $_[0];
build_project(
"${path}modules:xml:macbuild:XML.mcp", '',
"${path}build:mac:Mozilla.BuildLog.part"
);
}
1;
=pod
=back
=head1 HISTORY
=over 4
=item v1.02, September 23, 1998
Made fixes in finding and saving location of CodeWarrior IDE.
=item v1.01, June 1, 1998
Made fixes to C<chdir()> in C<activate()>, made C<activate()> more robust
in finding CodeWarrior IDE, added global variable to NOT switch to IDE
for each sent event, a few other fixes.
=item v1.00, May 30, 1998
First shot
=back
=head1 AUTHORS
Chris Nandor F<E<lt>pudge@pobox.comE<gt>>, and the author of the
original I<CodeWarriorLib>, Scott Collins F<E<lt>scc@netscape.comE<gt>>.
=head1 SEE ALSO
BuildProject L<Moz>.
=head1 COPYRIGHT
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 Communicator client code, released
March 31, 1998.
The Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1998-1999 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
=cut

View File

@@ -1,573 +0,0 @@
#!perl -w
package Moz::Jar;
#
# Module for creating jar files, either using a jar manifest, or
# simply jarring up folders on disk.
#
require 5.004;
require Exporter;
use strict;
use Archive::Zip;
use File::Path;
use Mac::Files;
use Moz::Moz;
use vars qw( @ISA @EXPORT );
@ISA = qw(Exporter);
@EXPORT = qw(
CreateJarFileFromDirectory
CreateJarFromManifest
WriteOutJarFiles
SanityCheckJarOptions
);
#-------------------------------------------------------------------------------
# Add the contents of a directory to the zip file
#
#-------------------------------------------------------------------------------
sub _addDirToJar($$$$)
{
my($dir, $jar_root, $zip, $compress) = @_;
opendir(DIR, $dir) or die "Error: Cannot open dir $dir\n";
my @files = readdir(DIR);
closedir DIR;
my $unix_jar_root = $jar_root;
$unix_jar_root =~ s|:|/|g; # colon to slash conversion
my $file;
foreach $file (@files)
{
my $filepath = $dir.":".$file;
if (-d $filepath)
{
print "Adding files to jar from $filepath\n";
_addDirToJar($filepath, $jar_root, $zip, $compress);
}
else
{
my $member = Archive::Zip::Member->newFromFile($filepath);
die "Error: Failed to create zip file member $filepath\n" unless $member;
my $unixName = $filepath;
$unixName =~ s|:|/|g; # colon to slash conversion
$unixName =~ s|^$unix_jar_root||; # relativise
$member->fileName($unixName);
# print "Adding $file as $unixName\n";
if ($compress) {
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_DEFLATED);
} else {
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_STORED);
}
$zip->addMember($member);
}
}
}
#-------------------------------------------------------------------------------
# Add the contents of a directory to the zip file
#
#-------------------------------------------------------------------------------
sub CreateJarFileFromDirectory($$$)
{
my($srcdir, $jarpath, $compress) = @_;
my $zip = Archive::Zip->new();
_addDirToJar($srcdir, $srcdir, $zip, $compress);
print "Saving zip file...\n";
my $status = $zip->writeToFileNamed($jarpath);
if ($status == 0) {
print "Zipping completed successfully\n";
} else {
print "Error saving zip file\n";
}
# set the file type/creator to something reasonable
MacPerl::SetFileInfo("ZIP ", "ZIP ", $jarpath);
}
#-------------------------------------------------------------------------------
# printZipContents
#
#-------------------------------------------------------------------------------
sub printZipContents($)
{
my($zip) = @_;
my(@members) = $zip->memberNames();
print "Zip contains:\n";
my($member);
foreach $member (@members)
{
print " $member\n";
}
}
#-------------------------------------------------------------------------------
# safeSaveJarFile
#
# Archive::Zip has a problem where you cannot save a zip file on top of
# an existing zip file that it has open, because it holds references
# into that zip. So we have to save to a temp file, then do a swap.
#
# Note that the zip will become invalid after this operation.
# If you want to do further operations on it, you'll have to reread it.
#-------------------------------------------------------------------------------
sub safeSaveJarFile($$)
{
my($zip, $full_dest_path) = @_;
my($temp_file_name) = $full_dest_path."_temp";
($zip->writeToFileNamed($temp_file_name) == Archive::Zip::AZ_OK) || die "Error: died writing jar to temp file $temp_file_name\n";
unlink $full_dest_path;
(rename $temp_file_name, $full_dest_path) || die "Error: Failed to rename $temp_file_name\n";
MacPerl::SetFileInfo("ZIP ", "ZIP ", $full_dest_path);
}
#-------------------------------------------------------------------------------
# addToJarFile
#
# Add a file to a jar file
#
# Parameters:
# 1. Jar ID. Unix path of jar file inside chrome.
# 2. Abs path to jar.mn file (i.e. source) (mac breaks)
# 3. File source, relative to jar.mn path (mac breaks)
# 4. Abs path to the resulting .jar file (mac breaks)
# 5. Relative file path within the jar (unix breaks)
# 6. Reference to hash of jar files
#
#-------------------------------------------------------------------------------
sub addToJarFile($$$$$$$)
{
my($jar_id, $jar_man_dir, $file_src, $jar_path, $file_jar_path, $override, $jars) = @_;
# print "addToJarFile with:\n $jar_man_dir\n $file_src\n $jar_path\n $file_jar_path\n";
unless ($jar_path =~ m/(.+:)([^:]+)$/) { die "Error: Bad jar path $jar_path\n"; }
my($target_dir) = $1;
my($jar_name) = $2;
$target_dir =~ s/[^:]+$//;
# print "¥ $target_dir $jar_name\n";
# find the source file
my($src) = $jar_man_dir.":".$file_src;
if ((!-e $src) && ($file_src =~ m/.+:([^:]+)$/)) # src does not exist. Fall back to looking for src in jar.mn dir
{
$file_src = $1;
$src = $jar_man_dir.":".$file_src;
if (!-e $src) {
die "Error: Can't find chrome file $src\n";
}
}
if ($main::options{chrome_jars})
{
my($zip) = $jars->{$jar_id};
unless ($zip) { die "Error: Can't find Zip entry for $jar_id\n"; }
# print "Adding $file_src to jar file $jar_path at $file_jar_path\n";
my($member) = Archive::Zip::Member->newFromFile($src);
unless ($member) { die "Error: Failed to create zip file member $src\n"; }
$member->fileName($file_jar_path);
my($compress) = 1;
if ($compress) {
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_DEFLATED);
$member->desiredCompressionLevel(Archive::Zip::COMPRESSION_LEVEL_DEFAULT); # defaults to 6
} else {
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_STORED);
}
my($old_member) = $zip->memberNamed($file_jar_path);
if ($override)
{
if ($old_member)
{
# print "Overriding $file_jar_path in jar file $jar_id\n";
# need to compare mod dates or use the + here
$zip->removeMember($old_member);
}
$zip->addMember($member);
}
else
{
if ($old_member)
{
#compare dates here
my($member_moddate) = $old_member->lastModTime();
my($file_moddate) = GetFileModDate($src);
if ($file_moddate > $member_moddate)
{
print "Updating older file $file_jar_path in $jar_id\n";
$zip->removeMember($old_member);
$zip->addMember($member);
}
else
{
print "File $file_jar_path in $jar_id is more recent. Not updating.\n";
}
}
else
{
$zip->addMember($member);
}
}
}
if ($main::options{chrome_files}) # we install raw files too
{
my($rel_path) = $file_jar_path;
$rel_path =~ s|/|:|g; # slash to colons
my($dir_name) = $jar_name;
$dir_name =~ s/\.jar$//;
my($dst) = $target_dir.$dir_name.":".$rel_path;
# print "Aliassing $src\n to\n$dst\n";
if ($override)
{
unlink $dst;
MakeAlias($src, $dst); # don't check errors, otherwise we fail on replacement
}
else
{
if (-e $dst)
{
#compare dates here
my($dst_moddate) = GetFileModDate($dst);
my($file_moddate) = GetFileModDate($src);
if ($file_moddate > $dst_moddate)
{
print "Updating older file $rel_path in $dir_name\n";
unlink $dst;
MakeAlias($src, $dst);
}
else
{
print "File $file_jar_path in $jar_id is more recent. Not updating.\n";
}
}
else
{
MakeAlias($src, $dst);
}
}
}
}
#-------------------------------------------------------------------------------
# setupJarFile
#
# setup a zip for writing
#-------------------------------------------------------------------------------
sub setupJarFile($$$)
{
my($jar_id, $dest_path, $jar_hash) = @_;
# print "Creating jar file $jar_id at $jar_path\n";
my($jar_file) = $jar_id;
$jar_file =~ s|/|:|g; # slash to colons
my($full_jar_path) = full_path_to($dest_path.":".$jar_file);
if ($main::options{chrome_jars})
{
my($zip) = $jar_hash->{$jar_id};
if (!$zip) # if we haven't made it already, do so
{
my($zip) = Archive::Zip->new();
$jar_hash->{$jar_id} = $zip;
# does the jar file exist already? If so, read it in
if (-e $full_jar_path)
{
print "Reading in jar file $jar_id\n";
if ($zip->read($full_jar_path) != Archive::Zip::AZ_OK) { die "Error: Failed to re-read $full_jar_path\n"; }
# printZipContents($zip);
}
}
}
else
{
# installing files.
# nothing to do. MakeAlias creates dirs as needed.
# add this jar to the list
$jar_hash->{$jar_id} = 1;
}
}
#-------------------------------------------------------------------------------
# closeJarFile
#
# We're done with this jar file _for this jar.mn_. We may add more entries
# to it later, so keep it open in the hash.
#-------------------------------------------------------------------------------
sub closeJarFile($$)
{
my($jar_path, $jar_hash) = @_;
# print "Closing jar file $jar_path\n";
if ($main::options{chrome_jars})
{
}
else
{
# installing files.
# nothing to do
}
}
#-------------------------------------------------------------------------------
# WriteOutJarFiles
#
# Now we dump out the jars
#-------------------------------------------------------------------------------
sub WriteOutJarFiles($$)
{
my($chrome_dir, $jars) = @_;
unless ($main::options{chrome_jars}) { return; }
my($full_chrome_path) = full_path_to($chrome_dir);
my($key);
foreach $key (keys %$jars)
{
my($zip) = $jars->{$key};
my($rel_path) = $key;
$rel_path =~ s/\//:/g;
my($output_path) = $full_chrome_path.":".$rel_path;
print "Writing zip file $key to $output_path\n";
# ensure the target dirs exist
my($path) = $output_path;
$path =~ s/[^:]+$//;
mkpath($path);
# unlink $output_path; # remove any existing jar
safeSaveJarFile($zip, $output_path);
# $zip is invalid after this operation, so nuke it here
$jars->{$key} = 0;
}
}
#-------------------------------------------------------------------------------
# registerChromePackage
#
# Enter a chrome package into the installed-chrome.txt file
#-------------------------------------------------------------------------------
sub registerChromePackage($$$$$$)
{
my($jar_file, $file_path, $chrome_dir, $jar_hash, $chrome_type, $pkg_name) = @_;
my($manifest_subdir) = $jar_file;
$manifest_subdir =~ s/:/\//g;
my($chrome_entry);
if ($main::options{use_jars}) {
$chrome_entry = "$chrome_type,install,url,jar:resource:/chrome/$manifest_subdir!/$chrome_type/$pkg_name";
} else {
$manifest_subdir =~ s/\.jar$//;
$chrome_entry = "$chrome_type,install,url,resource:/chrome/$manifest_subdir/$chrome_type/$pkg_name";
}
# print "Entering $chrome_entry in installed-chrome.txt\n";
# ensure chrome_dir exists
mkpath($chrome_dir);
my($inst_chrome) = ${chrome_dir}.":installed-chrome.txt";
if (open(CHROMEFILE, "<$inst_chrome")) {
while (<CHROMEFILE>) {
chomp;
if ($_ eq $chrome_entry) {
# $chrome_entry already appears in installed-chrome.txt file
# just update the mod date
my $now = time;
utime($now, $now, $inst_chrome) || die "Error: Couldn't touch $inst_chrome";
print "+++ updating chrome $inst_chrome\n+++\t\t$chrome_entry\n";
close(CHROMEFILE) || die "Error: can't close $inst_chrome: $!";
return 0;
}
}
close(CHROMEFILE) || die "Error: can't close $inst_chrome: $!";
}
open(CHROMEFILE, ">>${inst_chrome}") || die "Error: Failed to open $inst_chrome\n";
print(CHROMEFILE "${chrome_entry}\n");
close(CHROMEFILE) || die "Error: Failed to close $inst_chrome\n";
print "+++ adding chrome $inst_chrome\n+++\t\t$chrome_entry\n";
}
#-------------------------------------------------------------------------------
# Create or add to a jar file from a jar.mn file.
# Both arguments are relative to the mozilla root dir.
#
#
#-------------------------------------------------------------------------------
sub CreateJarFromManifest($$$)
{
my($jar_man_path, $dest_path, $jars) = @_;
if ($main::options{chrome_jars}) {
print "Jarring from $jar_man_path\n";
}
if ($main::options{chrome_files}) {
print "Installing files from $jar_man_path\n";
}
$jar_man_path = full_path_to($jar_man_path);
$dest_path = full_path_to($dest_path);
# if the jars hash is empty, nuke installed-chrome.txt
if (! scalar(%$jars))
{
print "Nuking installed-chrome.txt\n";
my($installed_chrome) = $dest_path.":installed-chrome.txt";
# unlink $installed_chrome;
}
my $jar_man_dir = "";
my $jar_man_file = "";
if ($jar_man_path =~ /(.+):([^:]+)$/)
{
$jar_man_dir = $1; # no trailing :
$jar_man_file = $2;
}
# Keep a hash of jar files, keyed on relative jar path (e.g. "packages/core.jar")
# Entries are open Archive::Zips (if zipping), and installed-chrome entries.
my($jar_id) = ""; # Current foo/bar.jar from jar.mn file
my($jar_file) = ""; # relative path to jar file (from $dest_path), with mac separators
my($full_jar_path);
open(FILE, "<$jar_man_path") || die "Error: could not open \"$jar_man_path\": $!";
while (<FILE>)
{
my($line) = $_;
chomp($line);
# print "$line\n";
if ($line =~ /^\s*\#.*$/) { # skip comments
next;
}
if ($line =~/^([\w\d.\-\_\\\/]+)\:\s*$/) # line start jar file entries
{
$jar_id = $1;
$jar_file = $jar_id;
$jar_file =~ s|/|:|g; # slash to colons
$full_jar_path = $dest_path.":".$jar_file;
setupJarFile($jar_id, $dest_path, $jars);
}
elsif ($line =~ /^(\+?)\s+([\w\d.\-\_\\\/]+)\s*(\([\w\d.\-\_\\\/]+\))?$\s*/) # jar file entry
{
my($override) = ($1 eq "+");
my($file_dest) = $2;
my($file_src) = $3;
if ($file_src) {
$file_src = substr($file_src, 1, -1); #strip the ()
} else {
$file_src = $file_dest;
}
$file_src =~ s|/|:|g;
if ($jar_file ne "") # if jar is open, add to jar
{
if ($file_dest =~ /([\w\d.\-\_]+)\/([\w\d.\-\_\\\/]+)contents.rdf/)
{
my $chrome_type = $1;
my $pkg_name = $2;
registerChromePackage($jar_file, $file_dest, $dest_path, $jars, $chrome_type, $pkg_name);
}
addToJarFile($jar_id, $jar_man_dir, $file_src, $full_jar_path, $file_dest, $override, $jars);
}
else
{
die "Error: bad jar.mn format at $line\n";
}
}
elsif ($line =~ /^\s*$/ ) # blank line
{
if ($jar_file ne "") #if a jar file is open, close it
{
closeJarFile($full_jar_path, $jars);
$jar_file = "";
$full_jar_path = "";
}
}
}
close(FILE);
if ($jar_file ne "") #if a jar file is open, close it
{
closeJarFile($full_jar_path, $jars);
}
}
1;

View File

@@ -1,228 +0,0 @@
#!perl -w
package Moz::MacCVS;
# package Mac::Apps::MacCVS; this should really be the name of the package
# but due to our directory hierarchy in mozilla, I am not doing it
require 5.004;
require Exporter;
use strict;
use Exporter;
use vars qw($VERSION @ISA @EXPORT);
use Cwd;
use File::Basename;
use Mac::StandardFile;
use Mac::AppleEvents;
use Mac::AppleEvents::Simple;
@ISA = qw(Exporter);
@EXPORT = qw(new describe checkout update);
$VERSION = "1.00";
# If you want to understand the gobbldeygook that's used to build Apple Events,
# you should start by reading the AEGizmos documentation.
# Architecture:
# cvs session object:
# name - session name
# session_file - session file
#
#
my($last_error) = 0;
my($gAppSig) = 'Mcvs'; # MacCVS Pro
#
# utility routines
#
sub _checkForEventError($)
{
my($evt) = @_;
if ($evt->{ERRNO} != 0)
{
print STDERR "Error. Script returned '$evt->{ERROR} (error $evt->{ERRNO})\n";
$last_error = $evt->{ERRNO};
return 0;
}
return 1; # success
}
#
# Session object methods
#
sub new
{
my ( $proto, $session_file) = @_;
my $class = ref($proto) || $proto;
my $self = {};
if ( defined($session_file) && ( -e $session_file) )
{
$self->{"name"} = basename( $session_file );
$self->{"session_file"} = $session_file;
bless $self, $class;
return $self;
}
else
{
print STDERR "MacCVS->new cvs file < $session_file > does not exist\n";
return;
}
}
# makes sure that the session is open
# assertSessionOpen()
# returns 1 on success
sub assertSessionOpen()
{
my ($self) = shift;
$last_error = 0;
my($prm) =
q"'----':obj {form:name, want:type(alis), seld:TEXT(@), from:'null'()}";
my($evt) = do_event(qw/aevt odoc/, $gAppSig, $prm, $self->{session_file});
return _checkForEventError($evt);
}
# prints the cvs object, used mostly for debugging
sub describe
{
my($self) = shift;
$last_error = 0;
print "MacCVS:: name: ", $self->{name}, " session file: ", $self->{session_file}, "\n";
}
# checkout( self, module, revision, date)
# MacCVS checkout command
# returns 1 on success.
sub checkout()
{
my($self, $module, $revision, $date ) = @_;
unless( defined ($module) ) { $module = ""; } # get rid of the pesky undefined warnings
unless( defined ($revision) ) { $revision = ""; }
unless( defined ($date) ) { $date = ""; }
$last_error = 0;
$self->assertSessionOpen() || die "Error: failed to open MacCVS session file at $self->{session_file}\n";
my($revstring) = ($revision ne "") ? $revision : "(none)";
my($datestring) = ($date ne "") ? $date : "(none)";
print "Checking out $module with revision $revstring, date $datestring\n";
my($prm) =
q"'----':obj {form:name, want:type(docu), seld:TEXT(@), from:'null'()}, ".
q"modl:'TEXT'(@), tagr:'TEXT'(@), tagd:'TEXT'(@) ";
my($evt) = do_event(qw/MCvs cout/, $gAppSig, $prm, $self->{name}, $module, $revision, $date);
return _checkForEventError($evt);
}
# update( self, branch tag, list of paths)
# MacCVS udate command
# returns 1 on success.
# NOTE: MacCVS Pro does not correctly support this stuff yet (as of version 2.7d5).
sub update()
{
my($self, $branch, $paths ) = @_;
$last_error = 0;
$self->assertSessionOpen() || die "Error: failed to open MacCVS session file at $self->{session_file}\n";
if ($branch eq "HEAD") {
$branch = "";
}
my($paths_list) = "";
my($path);
foreach $path (@$paths)
{
if ($paths_list ne "") {
$paths_list = $paths_list.", ";
}
$paths_list = $paths_list."Ò".$path."Ó";
}
my($prm) =
q"'----':obj {form:name, want:type(docu), seld:TEXT(@), from:'null'()}, ".
q"tagr:'TEXT'(@), tFls:[";
$prm = $prm.$paths_list."]";
my($evt) = do_event(qw/MCvs updt/, $gAppSig, $prm, $self->{name}, $branch);
return _checkForEventError($evt);
};
sub getLastError()
{
return $last_error;
}
1;
=pod
=head1 NAME
MacCVS - Interface to MacCVS
=head1 SYNOPSIS
use MacCVS;
$session = MacCVS->new( <session_file_path>) || die "cannot create session";
$session->checkout([module] [revision] [date]) || die "Could not check out";
=head1 DESCRIPTION
This is a MacCVS interface for talking to MacCVS Pro client.
MacCVSSession is the class used to manipulate the session
=item new
MacCVS->new( <cvs session file path>);
Creates a new session. Returns undef on failure.
=item checkout( <module> [revision] [date] )
cvs checkout command. Revision and date are optional
returns 0 on failure
=cut
=head1 SEE ALSO
=over
=item MacCVS Home Page
http://www.maccvs.org/
=back
=head1 AUTHORS
Aleks Totic atotic@netscape.com
Simon Fraser sfraser@netscape.com
=cut
__END__

View File

@@ -1,603 +0,0 @@
=head1 NAME
B<Moz> - routines for automating CodeWarrior builds, and some extra-curricular
activities related to building Mozilla
=head1 SYNOPSIS
use Moz;
OpenErrorLog(":::BuildLog");
StopForErrors();
$Moz::QUIET = 1;
InstallFromManifest(":projects:MANIFEST", $dist_dir);
BuildProjectClean(":projects:SomeProject.mcp", "SomeTarget");
MakeAlias(":projects:SomeProject.shlb", $dist_dir);
DontStopForErrors();
BuildProject(":projects:SomeOtherProject.mcp", "SomeTarget");
=head1 DESCRIPTION
B<Moz> comprises the routines needed to slap CodeWarrior around, force it
to build a sequence of projects, report the results, and a few other things.
This module should only contain functions that are generic to any build,
not just the Mozilla build.
=cut
package Moz::Moz;
require Exporter;
use Cwd;
use File::Copy;
use File::Path;
use File::Basename;
use Mac::Types;
use Mac::Events;
use Mac::Processes;
use ExtUtils::Manifest 'maniread';
use Moz::CodeWarriorLib;
@ISA = qw(Exporter);
@EXPORT = qw( LaunchCodeWarrior
GetCodeWarriorRelativePath
current_directory
full_path_to
DoBuildProject
ImportXMLProject
ExportProjectToXML
OpenErrorLog
MakeAlias
GetFileModDate
StopForErrors
DontStopForErrors
InstallFromManifest
InstallResources
RedirectOutputToFile
Delay
ActivateApplication
IsProcessRunning);
@EXPORT_OK = qw(CloseErrorLog QUIET);
sub current_directory()
{
my $current_directory = cwd();
chop($current_directory) if ( $current_directory =~ m/:$/ );
return $current_directory;
}
sub full_path_to($)
{
my ($path) = @_;
if ( $path =~ m/^[^:]+$/ )
{
$path = ":" . $path;
}
if ( $path =~ m/^:/ )
{
$path = current_directory() . $path;
}
return $path;
}
$logging = 0;
$recent_errors_file = "";
$stop_on_1st_error = 1;
$QUIET = 0;
=head2 Logging all the errors and warnings - C<OpenErrorLog($log_file)>, C<CloseErrorLog()>
The warnings and errors generated in the course of building projects can be logged to a file.
Tinderbox uses this facility to show why a remote build failed.
Logging is off by default.
Start logging at any point in your build process with C<OpenErrorLog($log_file)>.
Stop with C<CloseErrorLog()>.
You never need to close the log explicitly, unless you want to just log a couple of projects in the middle of a big list.
C<CloseErrorLog()> is not exported by default.
=cut
sub CloseErrorLog()
{
if ( $logging )
{
close(ERROR_LOG);
$logging = 0;
StopForErrors() if $stop_on_1st_error;
}
}
sub OpenErrorLog($)
{
my ($log_file) = @_;
CloseErrorLog();
if ( $log_file )
{
$log_file = full_path_to($log_file);
open(ERROR_LOG, ">$log_file") || die "Error: Can't open $log_file\n";
MacPerl::SetFileInfo("CWIE", "TEXT", $log_file);
$log_file =~ m/.+:(.+)/;
$recent_errors_file = full_path_to("$1.part");
$logging = 1;
}
}
=head2 Stopping before it's too late - C<StopForErrors()>, C<DontStopForErrors()>
When building a long list of projects, you decide whether to continue building subsequent projects when one fails.
By default, your build script will C<die> after the first project that generates an error while building.
Change this behavior with C<DontStopForErrors()>.
Re-enable it with C<StopForErrors()>.
=cut
sub StopForErrors()
{
$stop_on_1st_error = 1;
# Can't stop for errors unless we notice them.
# Can't notice them unless we are logging.
# If the user didn't explicitly request logging, log to a temporary file.
if ( ! $recent_errors_file )
{
OpenErrorLog("${TMPDIR}BuildResults");
}
}
sub DontStopForErrors()
{
$stop_on_1st_error = 0;
}
sub log_message($)
{
if ( $logging )
{
my ($message) = @_;
print ERROR_LOG $message;
}
}
sub log_message_with_time($)
{
if ( $logging )
{
my ($message) = @_;
my $time_stamp = localtime();
log_message("$message ($time_stamp)\n");
}
}
sub log_recent_errors($)
{
my ($project_name) = @_;
my $found_errors = 0;
if ( $logging )
{
open(RECENT_ERRORS, "<$recent_errors_file");
while( <RECENT_ERRORS> )
{
if ( /^Error/ || /^CouldnÕt find project file/ || /^Link Error/ )
{
# if (!$found_errors)
# print $_;
$found_errors = 1;
}
print ERROR_LOG $_;
}
close(RECENT_ERRORS);
unlink("$recent_errors_file");
}
if ( $stop_on_1st_error && $found_errors )
{
print ERROR_LOG "### Build failed.\n";
die "### Errors encountered building \"$project_name\".\n";
}
}
sub DoBuildProject($$$)
{
my ($project_path, $target_name, $clean_build) = @_;
$project_path = full_path_to($project_path);
# $project_path =~ m/.+:(.+)/;
# my $project_name = $1;
log_message_with_time("### Building \"$project_path\"");
# Check that the given project exists
if (! -e $project_path)
{
print ERROR_LOG "### Build failed.\n";
die "### Can't find project file \"$project_path\".\n";
}
print "Building \"$project_path\[$target_name\]\"\n";
$had_errors = Moz::CodeWarriorLib::build_project(
$project_path, $target_name, $recent_errors_file, $clean_build
);
WaitNextEvent();
# $had_errors =
#MacPerl::DoAppleScript(<<END_OF_APPLESCRIPT);
# tell (load script file "$CodeWarriorLib") to BuildProject("$project_path", "$project_name", "$target_name", "$recent_errors_file", $clean_build)
#END_OF_APPLESCRIPT
# Append any errors to the globally accumulated log file
# if ( $had_errors ) # Removed this test, because we want warnings, too. -- jrm
{
log_recent_errors($project_path);
}
}
sub ImportXMLProject($$)
{
my ($xml_path, $project_path) = @_;
# my ($codewarrior_ide_name) = Moz::CodeWarriorLib::getCodeWarriorIDEName();
# my $ascript = <<EOS;
# tell application "$codewarrior_ide_name"
# make new (project document) as ("$project_path") with data ("$xml_path")
# end tell
#EOS
# print $ascript."\n";
# my($result) = MacPerl::DoAppleScript($ascript);
# unless ($result) { die "Error: ImportXMLProject AppleScript failed $^E $result\n"; }
#
my($import_error) = Moz::CodeWarriorLib::import_project($xml_path, $project_path);
if ($import_error ne "") {
die "Error: ImportXMLProject failed with error $import_error\n";
}
}
sub ExportProjectToXML($$)
{
my ($project_path, $xml_path) = @_;
my (@suffix_list) = (".mcp");
my ($project_name, $project_dir, $suffix) = fileparse($project_path, @suffix_list);
if ($suffix eq "") { die "Project: $project_path doesn't look like a project file.\n"; }
if (-e $xml_path) {
print "$xml_path exists - not exporting $project_path\n";
}
else {
print "Exporting $project_path to $xml_path\n";
my($export_error) = Moz::CodeWarriorLib::export_project($project_path, $xml_path);
if ($export_error ne "") {
die "Error: export_project failed with error '$export_error'\n";
}
if (! -e $xml_path) {
die "Error: XML export to $xml_path failed\n";
}
}
}
=head2 Miscellaneous
C<MakeAlias($old_file, $new_file)> functions like C<symlink()>, except with better argument defaulting and more explicit error messages.
=cut
sub MakeAlias($$)
{
my ($old_file, $new_file) = @_;
# if the directory to hold $new_file doesn't exist, create it
if ( ($new_file =~ m/(.+:)/) && !-d $1 )
{
mkpath($1);
}
# if a leaf name wasn't specified for $new_file, use the leaf from $old_file
if ( ($new_file =~ m/:$/) && ($old_file =~ m/.+:(.+)/) )
{
$new_file .= $1;
}
my $message = "Can't create a Finder alias (at \"$new_file\")\n for \"$old_file\"; because ";
die "Error: $message \"$old_file\" doesn't exist.\n" unless -e $old_file;
die "Error: $message I won't replace an existing (non-alias) file with an alias.\n" if ( -e $new_file && ! -l $new_file );
# now: $old_file exists; $new_file doesn't (or else, is an alias already)
if ( -l $new_file )
{
# ...then see if it already points to $old_file
my $current_target = full_path_to(readlink($new_file));
my $new_target = full_path_to($old_file);
return if ( $current_target eq $new_target );
# if the desired alias already exists and points to the right thing, then we're done
unlink $new_file;
}
symlink($old_file, $new_file) || die "Error: $message symlink returned an unexpected error.\n";
}
=pod
C<InstallFromManifest()>
=cut
sub InstallFromManifest($;$$)
{
my ($manifest_file, $dest_dir, $flat) = @_;
$flat = 0 unless defined($flat); # if $flat, all rel. paths in MANIFEST get aliased to the root of $dest_dir
$dest_dir ||= ":";
$manifest_file =~ m/(.+):/;
my $source_dir = $1;
chop($dest_dir) if $dest_dir =~ m/:$/;
#Mac::Events->import();
WaitNextEvent();
if ($flat)
{
print "Doing manifest on \"$manifest_file\" FLAT\n" unless $QUIET;
}
else
{
print "Doing manifest on \"$manifest_file\"\n" unless $QUIET;
}
my $read = maniread(full_path_to($manifest_file));
foreach $file (keys %$read)
{
next unless $file;
$subdir = ":";
if (!$flat && ($file =~ /:.+:/ ))
{
$subdir = $&;
}
$file = ":$file" unless $file =~ m/^:/;
MakeAlias("$source_dir$file", "$dest_dir$subdir");
}
}
=pod
C<InstallResources()>
=cut
# parameters are path to MANIFEST file, destination dir, true (to make copies) or false (to make aliases)
sub InstallResources($;$;$)
{
my ($manifest_file, $dest_dir, $copy_files) = @_;
$dest_dir ||= ":";
mkpath($dest_dir) if !-d $dest_dir;
$manifest_file =~ m/(.+):/;
my $source_dir = $1;
chop($dest_dir) if $dest_dir =~ m/:$/;
WaitNextEvent();
print "Installing resources from \"$manifest_file\"\n" unless $QUIET;
my $read = maniread(full_path_to($manifest_file));
foreach $file (keys %$read)
{
next unless $file;
if ($copy_files)
{
copy("$source_dir:$file", "$dest_dir:$file");
}
else
{
MakeAlias("$source_dir:$file", "$dest_dir:$file");
}
}
}
#//--------------------------------------------------------------------------------------------------
#// Delay
#//--------------------------------------------------------------------------------------------------
sub Delay($)
{
my ($delay_seconds) = @_;
$now = time;
$exit_time = $now + $delay_seconds;
while ($exit_time > $now) {
$now = time;
}
}
#//--------------------------------------------------------------------------------------------------
#// GetFileModDate
#//--------------------------------------------------------------------------------------------------
sub GetFileModDate($)
{
my($filePath)=@_;
my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = stat($filePath);
return $mtime;
}
#//--------------------------------------------------------------------------------------------------
#// LaunchCodeWarrior
#//--------------------------------------------------------------------------------------------------
sub LaunchCodeWarrior($)
{
my($idepath_file) = @_; # full path to IDE location file
my($cur_dir) = cwd();
# this both launches and writes the IDE path file
Moz::CodeWarriorLib::activate($idepath_file);
chdir($cur_dir);
}
#//--------------------------------------------------------------------------------------------------
#// GetCodeWarriorRelativePath
#//--------------------------------------------------------------------------------------------------
sub GetCodeWarriorRelativePath($)
{
my($rel_path) = @_;
return Moz::CodeWarriorLib::getCodeWarriorPath($rel_path);
}
#//--------------------------------------------------------------------------------------------------
#// RedirectOutputToFile
#//--------------------------------------------------------------------------------------------------
sub RedirectOutputToFile($)
{
my($log_file) = @_;
# ensure that folders in the path exist
my($logdir) = "";
my($logfile) = $log_file;
if ($log_file =~ /(.+?:)([^:]+)$/) # ? for non-greedy match
{
$logdir = $1;
$logfile = $2;
mkpath($logdir);
}
print "Output is now being redirected to the file '$log_file'\n";
open(STDOUT, "> $log_file") || die "Can't redirect stdout";
open(STDERR, ">&STDOUT") || die "Can't dup stdout";
select(STDERR); $| = 1; # make unbuffered
select(STDOUT); $| = 1; # make unbuffered
MacPerl::SetFileInfo("CWIE", "TEXT", $log_file);
}
#//--------------------------------------------------------------------------------------------------
#// ActivateApplication
#//--------------------------------------------------------------------------------------------------
sub ActivateApplication($)
{
my ($appSignature) = @_;
my ($psi, $found);
my ($appPSN);
$found = 0;
foreach $psi (values(%Process))
{
if ($psi->processSignature() eq $appSignature)
{
$appPSN = $psi->processNumber();
$found = 1;
last;
}
}
if ($found == 0 || SameProcess($appPSN, GetFrontProcess()))
{
return;
}
SetFrontProcess($appPSN);
while (GetFrontProcess() != $appPSN)
{
WaitNextEvent();
}
}
#//--------------------------------------------------------------------------------------------------
#// IsProcessRunning
#//--------------------------------------------------------------------------------------------------
sub IsProcessRunning($)
{
my($processName, $psn, $psi) = @_;
while ( ($psn, $psi) = each(%Process) ) {
if ($psi->processName eq $processName) { return 1; }
}
return 0;
}
1;
=head1 AUTHORS
Scott Collins <scc@netscape.com>, Simon Fraser <sfraser@netscape.com>, Chris Yeh <cyeh@netscape.com>
=head1 SEE ALSO
BuildMozillaDebug.pl (et al), BuildList.pm, CodeWarriorLib (an AppleScript library)
=head1 COPYRIGHT
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 Communicator client code, released
March 31, 1998.
The Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1998-1999 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
=cut

View File

@@ -1,272 +0,0 @@
package Moz::Prefs;
require 5.004;
require Exporter;
# Package that attempts to read a file from the Preferences folder,
# and get build settings out of it
use strict;
use Exporter;
use File::Path;
use Mac::Files;
use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(ReadMozUserPrefs);
#-------------------------------------------------------------------------------
#
# GetPrefsFolder
#
#-------------------------------------------------------------------------------
sub GetPrefsFolder()
{
my($prefs_folder) = FindFolder(kOnSystemDisk, kPreferencesFolderType, 1);
return $prefs_folder.":Mozilla build prefs";
}
#-------------------------------------------------------------------------------
#
# SetArrayValue
#
#-------------------------------------------------------------------------------
sub SetArrayValue($$$)
{
my($array_ref, $index1, $index2) = @_;
my($index);
foreach $index (@$array_ref)
{
if ($index->[0] eq $index1)
{
$index->[1] = $index2;
return 1;
}
}
return 0;
}
#-------------------------------------------------------------------------------
#
# WriteDefaultPrefsFile
#
#-------------------------------------------------------------------------------
sub WriteDefaultPrefsFile($)
{
my($file_path) = @_;
my($file_contents);
$file_contents = <<'EOS';
% You can use this file to customize the Mozilla build system.
% The following kinds of lines are allowable:
% Comment lines, which start with a '%' in the first column
% Lines which modify the default build settings. For the list of flags,
% see MozBuildFlags.pm. Examples are:
%
% build pull 0 % don't pull
% options mng 1 % turn mng on
%
% Line containing the special 'buildfrom' flag, which specifies
% where to start the build. Example:
%
% buildfrom nglayout % where to start the build
%
% Lines which specify the location of the files used to store paths
% to the CodeWarrior IDE, and the MacCVS Pro session file. Note quoting
% of paths containing whitespace. Examples:
%
% filepath idepath ::codewarrior.txt
% filepath sessionpath ":Some folder:MacCVS session path.txt"
%
% Lines which modify the build settings like %main::DEBUG.
% Any lines which do not match either of the above are assumed
% to set variables on $main::. Examples:
%
% MOZILLA_OFFICIAL 1
%
EOS
$file_contents =~ s/%/#/g;
local(*PREFS_FILE);
open(PREFS_FILE, "> $file_path") || die "Could not write default prefs file\n";
print PREFS_FILE ($file_contents);
close(PREFS_FILE);
MacPerl::SetFileInfo("McPL", "TEXT", $file_path);
}
#-------------------------------------------------------------------------------
#
# HandlePrefSet
#
#-------------------------------------------------------------------------------
sub HandlePrefSet($$$$)
{
my($flags, $name, $value, $desc) = @_;
if (SetArrayValue($flags, $name, $value)) {
print "Prefs set $desc flag '$name' to '$value'\n";
} else {
die "$desc setting '$name' is not a valid option\n";
}
}
#-------------------------------------------------------------------------------
#
# HandleBuildFromPref
#
#-------------------------------------------------------------------------------
sub HandleBuildFromPref($$)
{
my($build_array, $name) = @_;
my($setting) = 0;
my($index);
foreach $index (@$build_array)
{
if ($index->[0] eq $name) {
$setting = 1;
}
$index->[1] = $setting;
}
if ($setting == 1) {
print "Building from $name onwards, as specified by prefs\n";
} else {
printf "Failed to find buildfrom setting '$name'\n";
}
}
#-------------------------------------------------------------------------------
#
# ReadPrefsFile
#
#-------------------------------------------------------------------------------
sub ReadPrefsFile($$$$$)
{
my($file_path, $build_flags, $options_flags, $filepath_flags, $create_if_missing) = @_;
local(*PREFS_FILE);
if (open(PREFS_FILE, "< $file_path"))
{
print "Reading build prefs from '$file_path'\n";
while (<PREFS_FILE>)
{
my($line) = $_;
chomp($line);
if ($line =~ /^\#/ || $line =~ /^\s*$/) { # ignore comments and empty lines
next;
}
if (($line =~ /^\s*([^#\s]+)\s+([^#\s]+)\s+\"(.+)\"(\s+#.+)?/) ||
($line =~ /^\s*([^#\s]+)\s+([^#\s]+)\s+\'(.+)\'(\s+#.+)?/) ||
($line =~ /^\s*([^#\s]+)\s+([^#\s]+)\s+([^#\s]+)(\s+#.+)?/))
{
my($array_name) = $1;
my($option_name) = $2;
my($option_value) = $3;
# print "Read '$array_name' '$option_name' '$option_value'\n";
if ($array_name eq "build")
{
HandlePrefSet($build_flags, $option_name, $option_value, "Build");
}
elsif ($array_name eq "options")
{
HandlePrefSet($options_flags, $option_name, $option_value, "Options");
}
elsif ($array_name eq "filepath" && $option_name && $option_value)
{
HandlePrefSet($filepath_flags, $option_name, $option_value, "Filepath");
}
else
{
print "Unknown pref option at $line\n";
}
}
elsif ($line =~ /^\s*buildfrom\s+([^#\s]+)(\s+#.+)?/)
{
my($build_start) = $1;
HandleBuildFromPref($build_flags, $build_start);
}
elsif ($line =~ /^\s*([^#\s]+)\s+([^#\s]+)(\s+#.+)?/)
{
my($build_var) = $1;
my($var_setting) = $2;
print "Setting \$main::$build_var to $var_setting\n";
eval "\$main::$build_var = \"$var_setting\"";
}
else
{
print "Unrecognized input line at $line\n";
}
}
close(PREFS_FILE);
}
elsif ($create_if_missing)
{
print "No prefs file found at $file_path; using defaults\n";
my($folder_path) = $file_path;
$folder_path =~ s/[^:]+$//;
mkpath($folder_path);
WriteDefaultPrefsFile($file_path);
}
}
#-------------------------------------------------------------------------------
#
# ReadMozUserPrefs
#
#-------------------------------------------------------------------------------
sub ReadMozUserPrefs($$$$)
{
my($prefs_file_name, $build_flags, $options_flags, $filepath_flags) = @_;
if ($prefs_file_name eq "") { return; }
# if local prefs exist, just use those. Othewise, look in the prefs folder
if (-e $prefs_file_name)
{
# read local prefs
ReadPrefsFile($prefs_file_name, $build_flags, $options_flags, $filepath_flags, 0);
}
else
{
# first read prefs folder prefs
my($prefs_path) = GetPrefsFolder();
$prefs_path .= ":$prefs_file_name";
ReadPrefsFile($prefs_path, $build_flags, $options_flags, $filepath_flags, 1);
}
}
1;

View File

@@ -1,932 +0,0 @@
#!/usr/bin/perl
#
# 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 Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Simon Fraser <sfraser@netscape.com>
#
package Moz::ProjectXML;
require 5.004;
require Exporter;
use strict;
use Exporter;
use Cwd;
use XML::DOM;
use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(
ParseXMLDocument
DisposeXMLDocument
WriteXMLDocument
CleanupPro5XML
GetTargetsList
CloneTarget
SetAsSharedLibraryTarget
SetAsStaticLibraryTarget
AddTarget
RemoveTarget
GetTargetSetting
SetTargetSetting
getChildElementTextContents
);
#--------------------------------------------------------------------------------------------------
# A module for reading, manipulating, and writing XML-format CodeWarrior project files.
#
# Sample usage:
#
# use ProjectXML;
#
# my $doc = ProjectXML::ParseXMLDocument("Test.mcp.xml");
# ProjectXML::CloneTarget($doc, "Test.shlb", "Test.lib");
# ProjectXML::SetAsStaticLibraryTarget($doc, "Test.lib", "TestOutput.lib");
# ProjectXML::WriteXMLDocument($doc, "Test_out.xml");
# ProjectXML::DisposeXMLDocument($doc);
#
#--------------------------------------------------------------------------------------------------
#//--------------------------------------------------------------------------------------------------
#// ParseXMLDocument
#// Note that the caller must call DisposeXMLDocument on the returned doc
#//--------------------------------------------------------------------------------------------------
sub ParseXMLDocument($)
{
my($doc_path) = @_;
my $parser = new XML::DOM::Parser(ErrorContext => 2);
my $doc = $parser->parsefile($doc_path);
return $doc;
}
#//--------------------------------------------------------------------------------------------------
#// DisposeXMLDocument
#// Needed to avoid memory leaks - cleanup circular references for garbage collection
#//--------------------------------------------------------------------------------------------------
sub DisposeXMLDocument($)
{
my($doc) = @_;
$doc->dispose();
}
#//--------------------------------------------------------------------------------------------------
#// WriteXMLDocument
#//--------------------------------------------------------------------------------------------------
sub _pro5_tag_compression($$)
{
return 1; # Pro 5 is broken and can't import XML with <foo/> style tags
}
sub _pro6plus_tag_compression($$)
{
return 0; # Pro 6 can deal with empty XML tags like <foo/>
}
sub WriteXMLDocument($$$)
{
my($doc, $file_path, $ide_version) = @_;
if ($ide_version eq "4.0")
{
XML::DOM::setTagCompression(\&_pro5_tag_compression);
}
else
{
XML::DOM::setTagCompression(\&_pro6plus_tag_compression);
}
$doc->printToFile($file_path);
}
#//--------------------------------------------------------------------------------------------------
#// CleanupPro5XML
#// XML Projects exported by Pro 5 contain garbage data under the MWMerge_MacOS_skipResources
#// setting. This routine cleans this up, saving the result to a new file
#//--------------------------------------------------------------------------------------------------
sub CleanupPro5XML($$)
{
my($xml_path, $out_path) = @_;
local(*XML_FILE);
open(XML_FILE, "< $xml_path") || die "Error: failed to open file $xml_path\n";
local(*CLEANED_FILE);
open(CLEANED_FILE, "> $out_path") || die "Error: failed to open file $out_path for writing\n";
my $in_skip_resources_settings = 0;
while(<XML_FILE>)
{
my($line) = $_;
if ($line =~ /^<\?codewarrior/) # is processing inst line
{
my $test_line = $line;
chomp($test_line);
my $out_line = $test_line;
if ($test_line =~ /^<\?codewarrior\s+exportversion=\"(.+)\"\s+ideversion=\"(.+)\"\s*\?>$/)
{
my $export_version = $1;
my $ide_version = $2;
$ide_version = "4.0_mozilla"; # pseudo IDE version so we know we touched it
$out_line = "<?codewarrior exportversion=\"".$export_version."\" ideversion=\"".$ide_version."\"?>";
}
print CLEANED_FILE "$out_line\n";
next;
}
if ($line =~ /MWMerge_MacOS_skipResources/)
{
$in_skip_resources_settings = 1;
print CLEANED_FILE "$line";
}
elsif($in_skip_resources_settings && $line =~ /<!-- Settings for/)
{
# leaving bad settings lines. Write closing tag
print CLEANED_FILE " <!-- Corrupted setting entries removed by script -->\n";
print CLEANED_FILE " </SETTING>\n\n";
print CLEANED_FILE "$line";
$in_skip_resources_settings = 0;
}
elsif (!$in_skip_resources_settings)
{
print CLEANED_FILE "$line";
}
}
close(XML_FILE);
close(CLEANED_FILE);
}
#--------------------------------------------------------------------------------------------------
# SniffProjectXMLIDEVersion
#
#--------------------------------------------------------------------------------------------------
sub SniffProjectXMLIDEVersion($)
{
my($xml_path) = @_;
my $found_version = "";
local(*XML_FILE);
open(XML_FILE, "< $xml_path") || die "Error: failed to open file $xml_path\n";
while(<XML_FILE>)
{
my($line) = $_;
chomp($line);
if ($line =~ /^<\?codewarrior/) # is processing inst line
{
unless ($line =~ /^<\?codewarrior\s+exportversion=\"(.+)\"\s+ideversion=\"(.+)\"\s*\?>$/)
{
die "Error: Failed to find ideversion in $xml_path in line $line\n";
}
my $export_version = $1;
my $ide_version = $2;
$found_version = $ide_version;
last;
}
}
close(XML_FILE);
return $found_version;
}
#//--------------------------------------------------------------------------------------------------
#// GetTargetsList
#// Returns an array of target names
#//--------------------------------------------------------------------------------------------------
sub GetTargetsList($)
{
my($doc) = @_;
my $nodes = $doc->getElementsByTagName("TARGET");
my $n = $nodes->getLength;
my @target_names;
for (my $i = 0; $i < $n; $i++)
{
my ($node) = $nodes->item($i);
my($target_name) = getChildElementTextContents($node, "NAME");
push(@target_names, $target_name);
}
return @target_names;
}
#//--------------------------------------------------------------------------------------------------
#// CloneTarget
#// Clone the named target, renaming it to 'new_name'
#//--------------------------------------------------------------------------------------------------
sub CloneTarget($$$)
{
my($doc, $target_name, $new_name) = @_;
my $target_node = getTargetNode($doc, $target_name);
# clone here
my $target_clone = $target_node->cloneNode(1); # deep clone
# -- munge target settings --
# set the target name field
setChildElementTextContents($doc, $target_clone, "NAME", $new_name);
# set the targetname pref
setTargetNodeSetting($doc, $target_clone, "Targetname", $new_name);
# -- insert new target subtree --
my $target_list = $target_node->getParentNode();
$target_list->appendChild($target_clone);
# -- now add to targetorder --
my (@target_order_nodes) = getChildOfDocument($doc, "TARGETORDER");
my $target_order = @target_order_nodes[0];
my $new_order = $doc->createElement("ORDEREDTARGET");
my $order_name = $doc->createElement("NAME");
$new_order->appendChild($order_name);
setChildElementTextContents($doc, $new_order, "NAME", $new_name);
$target_order->appendChild($new_order);
}
#//--------------------------------------------------------------------------------------------------
#// SetAsSharedLibraryTarget
#//
#//--------------------------------------------------------------------------------------------------
sub SetAsSharedLibraryTarget($$$)
{
my($doc, $target_name, $output_name) = @_;
my $target_node = getTargetNode($doc, $target_name);
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_type", "SharedLibrary");
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_filetype", "1936223330"); #'shlb'
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_outfile", $output_name);
}
#//--------------------------------------------------------------------------------------------------
#// AddFileToTarget
#//
#// Add a file to the specified target(s).
#//
#//--------------------------------------------------------------------------------------------------
sub AddFileToTarget($$$)
{
my($doc, $target_list, $file_name) = @_;
# the file must be added in 3 places:
# 1. in <TARGET><FILELIST><FILE> (with linkage flags if necessary)
# 2. in <TARGET><LINKORDER><FILEREF>
# 3. in <GROUPLIST><GROUP><FILEREF>
die "Write me\n";
}
#//--------------------------------------------------------------------------------------------------
#// RemoveFileFromTarget
#//
#// Remove a file from the specified target, removing it from the entire project
#// if no other targets reference it.
#//
#//--------------------------------------------------------------------------------------------------
sub RemoveFileFromTarget($$$)
{
my($doc, $target_node, $file_name) = @_;
# the file must be removed in 3 places:
# 1. in <TARGET><FILELIST><FILE>
# 2. in <TARGET><LINKORDER><FILEREF>
# 3. in <GROUPLIST><GROUP><FILEREF>
# first, remove from <FILELIST>
my $filelist_node = getFirstChildElement($target_node, "FILELIST");
unless ($filelist_node) { die "Error: failed to find FILELIST node\n"; }
my $file_node = getChildNodeByGrandchildContents($doc, $filelist_node, "FILE", "PATH", $file_name);
unless ($file_node) { return; }
$filelist_node->removeChild($file_node);
# next, remove from <LINKORDER>
my $linkorder_node = getFirstChildElement($target_node, "LINKORDER");
unless ($linkorder_node) { die "Error: failed to find LINKORDER node\n"; }
my $fileref_node = getChildNodeByGrandchildContents($doc, $linkorder_node, "FILEREF", "PATH", $file_name);
unless ($fileref_node) { die "Error: link order node for file $file_name not found\n"; }
$linkorder_node->removeChild($fileref_node);
# last, remove from <GROUPLIST>
# <GROUPLIST> is cross-target, so we have to be careful here.
my $grouplist_node = getChildOfDocument($doc, "GROUPLIST");
unless ($grouplist_node) { die "Error: failed to find GROUPLIST node\n"; }
# if the file isn't in any other targets, remove it from the groups
if (!GetFileInUse($doc, $file_name))
{
print "File $file_name is in no other targest. Removing from project\n";
my @group_nodes;
getChildElementsOfType($doc, $grouplist_node, "GROUP", \@group_nodes);
my $group_node;
foreach $group_node (@group_nodes)
{
my @fileref_nodes;
getChildElementsOfType($doc, $group_node, "FILEREF", \@fileref_nodes);
my $fileref_node;
foreach $fileref_node (@fileref_nodes)
{
my $path_name = getChildElementTextContents($fileref_node, "PATH");
if ($path_name eq $file_name)
{
print "Removing $file_name from project group list\n";
$group_node->removeChild($fileref_node);
last;
}
}
# can a file appear in more than one group?
}
}
}
#//--------------------------------------------------------------------------------------------------
#// SetAsStaticLibraryTarget
#//
#//--------------------------------------------------------------------------------------------------
sub SetAsStaticLibraryTarget($$$)
{
my($doc, $target_name, $output_name) = @_;
my $target_node = getTargetNode($doc, $target_name);
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_type", "Library");
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_filetype", "1061109567"); #'????'
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_outfile", $output_name);
# static targets don't need any library linkage, so we can remove linkage
# with all .shlb and .Lib files.
my(@obsolete_files) = ("NSStdLibStubs", "InterfacesStubs", "InterfaceLib", "InternetConfigLib");
print " Removing libraries etc. from target\n";
# get all files in target
my @target_files = GetTargetFilesList($doc, $target_name);
my $target_file;
foreach $target_file (@target_files)
{
if ($target_file =~ /(\.shlb|\.lib|\.Lib|\.o|\.exp)$/)
{
RemoveFileFromTarget($doc, $target_node, $target_file);
}
}
print " Removing stub libraries from target\n";
# then remove files with known names
my $obs_file;
foreach $obs_file (@obsolete_files)
{
RemoveFileFromTarget($doc, $target_node, $obs_file);
}
}
#//--------------------------------------------------------------------------------------------------
#// AddTarget
#//
#//--------------------------------------------------------------------------------------------------
sub AddTarget($$)
{
my($doc, $target_name) = @_;
die "Write me\n";
}
#//--------------------------------------------------------------------------------------------------
#// RemoveTarget
#//
#//--------------------------------------------------------------------------------------------------
sub RemoveTarget($$)
{
my($doc, $target_name) = @_;
die "Write me\n";
}
#//--------------------------------------------------------------------------------------------------
#// GetTargetSetting
#// Get the value for the specified setting in the specified target
#//--------------------------------------------------------------------------------------------------
sub GetTargetSetting($$$)
{
my($doc, $target_name, $setting_name) = @_;
my $target_node = getTargetNode($doc, $target_name);
return getTargetNodeSetting($target_node, "VALUE");
}
#//--------------------------------------------------------------------------------------------------
#// SetTargetSetting
#// Set the value for the specified setting in the specified target
#//--------------------------------------------------------------------------------------------------
sub SetTargetSetting($$$$)
{
my($doc, $target_name, $setting_name, $new_value) = @_;
my $target_node = getTargetNode($doc, $target_name);
setTargetNodeSetting($doc, $target_node, "VALUE", $new_value);
}
#//--------------------------------------------------------------------------------------------------
#// GetTargetFilesList
#// Return an array of the files in the target (in filelist order)
#//--------------------------------------------------------------------------------------------------
sub GetTargetFilesList($$)
{
my($doc, $target_name) = @_;
my $target_node = getTargetNode($doc, $target_name);
my @files_list;
my $filelist_node = getFirstChildElement($target_node, "FILELIST");
unless ($filelist_node) { die "Error: failed to find FILELIST node\n"; }
my @file_nodes;
getChildElementsOfType($doc, $filelist_node, "FILE", \@file_nodes);
my $node;
foreach $node (@file_nodes)
{
my $file_name = getChildElementTextContents($node, "PATH");
push(@files_list, $file_name);
}
return @files_list;
}
#//--------------------------------------------------------------------------------------------------
#// FileIsInTarget
#//
#//--------------------------------------------------------------------------------------------------
sub FileIsInTarget($$$)
{
my($doc, $file_name, $target_name) = @_;
my $target_node = getTargetNode($doc, $target_name);
unless ($target_node) { die "Error: no target found called $target_name\n"; }
my $file_node = GetTargetFileNode($doc, $target_node, $file_name);
if ($file_node) {
return 1;
}
return 0;
}
#//--------------------------------------------------------------------------------------------------
#// GetFileTargetsList
#// Return an array of the targets that a file is in (expensive)
#//--------------------------------------------------------------------------------------------------
sub GetFileTargetsList($$)
{
my ($doc, $file_name) = @_;
my @target_list;
my @targets = GetTargetsList($doc);
my $target;
foreach $target (@targets)
{
if (FileIsInTarget($doc, $file_name, $target))
{
push(@target_list, $target);
}
}
return @target_list;
}
#//--------------------------------------------------------------------------------------------------
#// GetTargetFileNode
#//
#//--------------------------------------------------------------------------------------------------
sub GetTargetFileNode($$$)
{
my($doc, $target_node, $file_name) = @_;
my $filelist_node = getFirstChildElement($target_node, "FILELIST");
unless ($filelist_node) { die "Error: failed to find FILELIST node\n"; }
my $file_node = getChildNodeByGrandchildContents($doc, $filelist_node, "FILE", "PATH", $file_name);
return $file_node;
}
#//--------------------------------------------------------------------------------------------------
#// GetFileInUse
#// Return true if the file is used by any target
#//--------------------------------------------------------------------------------------------------
sub GetFileInUse($$)
{
my($doc, $file_name) = @_;
my $targetlist_node = getChildOfDocument($doc, "TARGETLIST");
my $target_node = $targetlist_node->getFirstChild();
while ($target_node)
{
if ($target_node->getNodeTypeName eq "ELEMENT_NODE" &&
$target_node->getTagName() eq "TARGET")
{
# if this is a target node
my $file_node = GetTargetFileNode($doc, $target_node, $file_name);
if ($file_node) {
return 1; # found it
}
}
$target_node = $target_node->getNextSibling();
}
# not found
return 0;
}
#//--------------------------------------------------------------------------------------------------
#// getChildOfDocument
#//--------------------------------------------------------------------------------------------------
sub getChildOfDocument($$)
{
my($doc, $child_type) = @_;
return getFirstChildElement($doc->getDocumentElement(), $child_type);
}
#//--------------------------------------------------------------------------------------------------
#// getFirstChildElement
#//--------------------------------------------------------------------------------------------------
sub getFirstChildElement($$)
{
my($node, $element_name) = @_;
my $found_node;
unless ($node) { die "getFirstChildElement called with empty node\n"; }
#look for the first "element_name" child
my $child_node = $node->getFirstChild();
while ($child_node)
{
if ($child_node->getNodeTypeName eq "ELEMENT_NODE" &&
$child_node->getTagName() eq $element_name)
{
$found_node = $child_node;
last;
}
$child_node = $child_node->getNextSibling();
}
return $found_node;
}
#//--------------------------------------------------------------------------------------------------
#// getChildElementsOfType
#//
#// Return an array of refs to child nodes of the given type
#//--------------------------------------------------------------------------------------------------
sub getChildElementsOfType($$$$)
{
my($doc, $node, $child_type, $array_ref) = @_;
my $child_node = $node->getFirstChild();
while ($child_node)
{
if ($child_node->getNodeTypeName eq "ELEMENT_NODE" &&
$child_node->getTagName() eq $child_type)
{
push(@$array_ref, $child_node);
}
$child_node = $child_node->getNextSibling();
}
}
#//--------------------------------------------------------------------------------------------------
#// getChildElementTextContents
#//--------------------------------------------------------------------------------------------------
#
# Given <FOOPY><NERD>Hi!</NERD></FOOPY>, where $node is <FOOPY>,
# returns "Hi!". If > 1 <NERD> node, returns the contents of the first.
#
sub getChildElementTextContents($$)
{
my($node, $tag_name) = @_;
my $first_element = getFirstChildElement($node, $tag_name);
my $text_node = $first_element->getFirstChild();
my $text_contents = "";
# concat adjacent text nodes
while ($text_node)
{
if ($text_node->getNodeTypeName() ne "TEXT_NODE")
{
last;
}
$text_contents = $text_contents.$text_node->getData();
$text_node = $text_node->getNextSibling();
}
return $text_contents;
}
#//--------------------------------------------------------------------------------------------------
#// setChildElementTextContents
#//--------------------------------------------------------------------------------------------------
sub setChildElementTextContents($$$$)
{
my($doc, $node, $tag_name, $contents_text) = @_;
my $first_element = getFirstChildElement($node, $tag_name);
my $new_text_node = $doc->createTextNode($contents_text);
# replace all child elements with a text element
removeAllChildren($first_element);
$first_element->appendChild($new_text_node);
}
#//--------------------------------------------------------------------------------------------------
#// getChildNodeByContents
#//
#// Consider <foo><bar><baz>Foopy</baz></bar><bar><baz>Loopy</baz></bar></foo>
#// This function, when called with getChildNodeByContents($foonode, "bar", "baz", "Loopy")
#// returns the second <bar> node.
#//--------------------------------------------------------------------------------------------------
sub getChildNodeByGrandchildContents($$$$$)
{
my($doc, $node, $child_type, $gc_type, $gc_contents) = @_; # gc = grandchild
my $found_node;
my $child_node = $node->getFirstChild();
while ($child_node)
{
if ($child_node->getNodeTypeName eq "ELEMENT_NODE" &&
$child_node->getTagName() eq $child_type)
{
# check for a child of this node of type
my $child_contents = getChildElementTextContents($child_node, $gc_type);
if ($child_contents eq $gc_contents)
{
$found_node = $child_node;
last;
}
}
$child_node = $child_node->getNextSibling();
}
return $found_node;
}
#//--------------------------------------------------------------------------------------------------
#// getTargetNode
#//--------------------------------------------------------------------------------------------------
sub getTargetNode($$)
{
my($doc, $target_name) = @_;
my $targetlist_node = getChildOfDocument($doc, "TARGETLIST");
return getChildNodeByGrandchildContents($doc, $targetlist_node, "TARGET", "NAME", $target_name);
}
#//--------------------------------------------------------------------------------------------------
#// getTargetNamedSettingNode
#//--------------------------------------------------------------------------------------------------
sub getTargetNamedSettingNode($$)
{
my($target_node, $setting_name) = @_;
my $setting_node;
my $settinglist_node = getFirstChildElement($target_node, "SETTINGLIST");
my $child_node = $settinglist_node->getFirstChild();
while ($child_node)
{
if ($child_node->getNodeTypeName ne "ELEMENT_NODE")
{
$child_node = $child_node->getNextSibling();
next;
}
if ($child_node->getTagName() eq "SETTING")
{
my $set_name = getChildElementTextContents($child_node, "NAME");
if ($set_name eq $setting_name)
{
$setting_node = $child_node;
last;
}
}
$child_node = $child_node->getNextSibling();
}
return $setting_node;
}
#//--------------------------------------------------------------------------------------------------
#// getTargetNodeSetting
#//--------------------------------------------------------------------------------------------------
sub getTargetNodeSetting($$)
{
my($target_node, $setting_name) = @_;
my $setting_node = getTargetNamedSettingNode($target_node, $setting_name);
return getChildElementTextContents($setting_node, "VALUE");
}
#//--------------------------------------------------------------------------------------------------
#// setTargetNodeSetting
#//--------------------------------------------------------------------------------------------------
sub setTargetNodeSetting($$$$)
{
my($doc, $target_node, $setting_name, $new_value) = @_;
my $setting_node = getTargetNamedSettingNode($target_node, $setting_name);
setChildElementTextContents($doc, $setting_node, "VALUE", $new_value);
}
#//--------------------------------------------------------------------------------------------------
#// elementInArray
#//--------------------------------------------------------------------------------------------------
sub elementInArray($$)
{
my($element, $array) = @_;
my $test;
foreach $test (@$array)
{
if ($test eq $element) {
return 1;
}
}
return 0;
}
#//--------------------------------------------------------------------------------------------------
#// removeAllChildren
#//--------------------------------------------------------------------------------------------------
sub removeAllChildren($)
{
my($node) = @_;
my $child_node = $node->getFirstChild();
while ($child_node)
{
$node->removeChild($child_node);
$child_node = $node->getFirstChild();
}
}
#//--------------------------------------------------------------------------------------------------
#// dumpNodeData
#//--------------------------------------------------------------------------------------------------
sub dumpNodeData($)
{
my($node) = @_;
unless ($node) { die "Null node passed to dumpNodeData\n"; }
print "Dumping node $node\n";
my($node_type) = $node->getNodeTypeName();
if ($node_type eq "ELEMENT_NODE")
{
my($node_name) = $node->getTagName();
print "Element $node_name\n";
}
elsif ($node_type eq "TEXT_NODE")
{
my($node_data) = $node->getData;
# my(@node_vals) = unpack("C*", $node_data);
print "Text '$node_data'\n"; # may contain LF chars
}
else
{
print "Node $node_type\n";
}
}
#//--------------------------------------------------------------------------------------------------
#// dumpNodeTree
#//--------------------------------------------------------------------------------------------------
sub dumpNodeTree($)
{
my($node) = @_;
my($child_node) = $node->getFirstChild();
unless ($child_node) { return; }
# recurse
dumpNodeData($child_node);
# then go through child nodes
while ($child_node)
{
dumpNodeTree($child_node);
$child_node = $child_node->getNextSibling();
}
}
1;

View File

@@ -1,90 +0,0 @@
#-------------------------------------------------------------------------------
# These 3 lists are the 'master lists' to control what gets built.
#
# Ordering in these arrays is important; it has to reflect the order in
# which the build occurs.
#
# Setting containing spaces must be quoted with double quotes.
#-------------------------------------------------------------------------------
build_flags
all 1
pull 0
dist 0
config 0
xpidl 0
idl 0
stubs 0
runtime 0
common 0
imglib 0
libimg2 0
necko 0
security 0
browserutils 0
intl 0
nglayout 0
accessiblity 0
editor 0
embedding 0
viewer 0
xpapp 0
extensions 0
plugins 0
mailnews 0
apprunner 0
resources 0
options_flags
pull_by_date 0
chrome_jars 1
chrome_files 0
use_jars 1
transformiix 1
mathml 0 MOZ_MATHML
svg 0 MOZ_SVG
# svg requires libart, which is an lgpl library. You need to pull it
# explicitly.
libart_lgpl 0
mng 1
ldap 1 MOZ_LDAP_XPCOM
ldap_experimental 0 MOZ_LDAP_XPCOM_EXPERIMENTAL
xmlextras 1
wsp 0 MOZ_WSP
inspector 1
mailextras 1
xptlink 0
psm 0 MOZ_PSM
embedding_test 1
embedding_chrome 0
embedding_xulprefs 0
embedding_xulsecurity 0
carbon 0 TARGET_CARBON
useimg2 1 USE_IMG2
lowmem 0 MOZ_MAC_LOWMEM
accessible 1 ACCESSIBILITY
bidi 1 IBMBIDI
p3p 0
jsd 1
venkman 1
moz_logging 1 MOZ_LOGGING
chatzilla 1
content_packs 1
xml_rpc 1
cview 1
help 1
timeline 0 MOZ_TIMELINE
static_build 0 MOZ_STATIC_COMPONENT_LIBS
string_debug 0 DEBUG_STRING
string_stats 0 DEBUG_STRING_STATS
xpctools 0 XPC_TOOLS_SUPPORT
smime 1
mdn 1
print_preview 1 NS_PRINT_PREVIEW
moz_xul 1 MOZ_XUL
filepath_flags
idepath ":CodeWarrior IDE Path.txt"
sessionpath ":Mozilla session path.txt"
buildlogfilepath ":Build Logs:Mozilla build log.txt" # this is a path
scriptlogfilepath ":Build Logs:Mozilla script log.txt"

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +0,0 @@
# List of modules to check out. Format is
# module, (tag), (date)
# where tag and date are optional (non-trailing commas are required)
#
# Examples:
# mozilla/nsprpub, NSPRPUB_CLIENT_TAG
# mozilla/gc, , 10/25/2000 12:00:00
#
mozilla/nsprpub, NETSCAPE_7_0_RTM
mozilla/security/nss, NETSCAPE_7_0_RTM
mozilla/security/manager, NETSCAPE_7_0_RTM
mozilla/accessible, NETSCAPE_7_0_RTM
mozilla/directory/c-sdk, NETSCAPE_7_0_RTM
mozilla/lib/mac/Instrumentation, NETSCAPE_7_0_RTM
mozilla/gfx2, NETSCAPE_7_0_RTM
mozilla/modules/libpr0n, NETSCAPE_7_0_RTM
SeaMonkeyAll, NETSCAPE_7_0_RTM
## You need this if you want to be able to use SVG
## Note that this library is under the LGPL, not the MPL
#mozilla/other-licenses/libart_lgpl

View File

@@ -1,79 +0,0 @@
#!perl
#
# 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 Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Simon Fraser <sfraser@netscape.com>
#
require 5.004;
use strict;
use Cwd;
use Moz::BuildUtils;
use Moz::BuildCore;
#-------------------------------------------------------------
# Where have the build options gone?
#
# The various build flags have been centralized into one place.
# The master list of options is in MozBuildFlags.txt. However,
# you should never need to edit that file, or this one.
#
# To customize what gets built, or where to start the build,
# edit the $prefs_file_name file in
# System Folder:Preferences:Mozilla build prefs:
# Documentation is provided in that file.
#-------------------------------------------------------------
my($prefs_file_name) = "Mozilla pull prefs";
#-------------------------------------------------------------
# hashes to hold build options
#-------------------------------------------------------------
my(%build);
my(%options);
my(%filepaths);
my(%optiondefines);
# Hash of input files for this build. Eventually, there will be
# input files for manifests, and projects too.
my(%inputfiles) = (
"buildflags", "MozillaBuildFlags.txt",
"checkoutdata", "MozillaCheckoutList.txt",
"buildprogress", "",
"buildmodule", "MozillaBuildList.pm",
"checkouttime", "Mozilla last checkout"
);
#-------------------------------------------------------------
# end build hashes
#-------------------------------------------------------------
# set the build root directory, which is the the dir above mozilla
SetupBuildRootDir(":mozilla:build:mac:build_scripts");
# Set up all the flags on $main::, like DEBUG, CARBON etc.
# Override the defaults using the preferences files.
SetupDefaultBuildOptions(0, ":mozilla:dist:viewer:", "");
my($do_checkout) = 1;
my($do_build) = 0;
RunBuild($do_checkout, $do_build, \%inputfiles, $prefs_file_name);

View File

@@ -1,511 +0,0 @@
# 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 Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=.
!if !defined(MOZ_TOP)
#enable builds from changed top level directories
MOZ_TOP=mozilla
!endif
MOZ_SRC_FLIPPED = $(MOZ_SRC:\=/)
MOZ_DIST_FLIPPED = $(MOZ_SRC_FLIPPED)/mozilla/dist
!ifdef MOZ_DEBUG
MOZ_OBJDIR = WIN32_D.OBJ
!else
MOZ_OBJDIR = WIN32_O.OBJ
!endif
#
# Command macro defines
#
#//------------------------------------------------------------------------
#// Figure out how to do the pull.
#//------------------------------------------------------------------------
# uncomment these, modify branch tag, and check in to branch for milestones
MOZ_BRANCH=NETSCAPE_7_0_RTM
NSPR_CO_TAG=NETSCAPE_7_0_RTM
PSM_CO_TAG=NETSCAPE_7_0_RTM
NSS_CO_TAG=NETSCAPE_7_0_RTM
LDAPCSDK_CO_TAG=NETSCAPE_7_0_RTM
ACCESSIBLE_CO_TAG=NETSCAPE_7_0_RTM
IMGLIB2_CO_TAG=NETSCAPE_7_0_RTM
GFX2_CO_TAG=NETSCAPE_7_0_RTM
!ifdef MOZ_BRANCH
CVS_BRANCH=-r $(MOZ_BRANCH)
!endif
!ifdef MOZ_DATE
CVS_BRANCH=$(CVS_BRANCH) -D "$(MOZ_DATE)"
!endif
# default pull is "quiet" but it can be overridden with MOZ_CVS_VERBOSE
!ifndef MOZ_CVS_VERBOSE
CVS_FLAGS=-q
!endif
# honor any user-defined CVS flags
!ifdef MOZ_CVS_FLAGS
CVS_FLAGS=$(CVS_FLAGS) $(MOZ_CVS_FLAGS)
!endif
# let's be explicit about CVSROOT... some windows cvs clients
# are too stupid to correctly work without the -d option
#
# if they are too stupid, they should fail. I am
# commenting this out because this does not work
# under 4nt. (%'s are evaluted differently)
#
# If it breaks you, mail dougt@netscape.com
# and leaf@mozilla.org
#
!if 0
!if defined(CVSROOT)
CVS_FLAGS=$(CVS_FLAGS) -d "$(CVSROOT)"
!endif
!endif
!ifndef MOZ_CO_FLAGS
MOZ_CO_FLAGS = -P
!endif
CVSCO = cvs $(CVS_FLAGS) co $(MOZ_CO_FLAGS) $(CVS_BRANCH)
#//------------------------------------------------------------------------
#// Figure out how to pull NSPR.
#// If no NSPR_CO_TAG is specified, use the default static tag
#//------------------------------------------------------------------------
!ifndef NSPR_CO_FLAGS
NSPR_CO_FLAGS=$(MOZ_CO_FLAGS)
!endif
NSPR_CO_FLAGS=$(NSPR_CO_FLAGS) $(CVS_BRANCH)
CVSCO_NSPR = cvs $(CVS_FLAGS) co $(NSPR_CO_FLAGS)
#//------------------------------------------------------------------------
#// Figure out how to pull NSS and PSM libs.
#// If no NSS_CO_TAG or PSM_CO_TAG is specified, use the default static tag
#//------------------------------------------------------------------------
!ifndef NSS_CO_FLAGS
NSS_CO_FLAGS=$(MOZ_CO_FLAGS)
!endif
NSS_CO_FLAGS=$(NSS_CO_FLAGS) $(CVS_BRANCH)
CVSCO_NSS = cvs $(CVS_FLAGS) co $(NSS_CO_FLAGS)
!ifndef PSM_CO_FLAGS
PSM_CO_FLAGS=$(MOZ_CO_FLAGS)
!endif
PSM_CO_FLAGS=$(PSM_CO_FLAGS) $(CVS_BRANCH)
CVSCO_PSM = cvs $(CVS_FLAGS) co $(PSM_CO_FLAGS)
#//------------------------------------------------------------------------
#// Figure out how to pull LDAP C SDK client libs.
#// If no LDAPCSDK_CO_TAG is specified, use the default tag
#//------------------------------------------------------------------------
!ifndef LDAPCSDK_CO_FLAGS
LDAPCSDK_CO_FLAGS=$(MOZ_CO_FLAGS)
!endif
LDAPCSDK_CO_FLAGS=$(LDAPCSDK_CO_FLAGS) $(CVS_BRANCH)
CVSCO_LDAPCSDK = cvs $(CVS_FLAGS) co $(LDAPCSDK_CO_FLAGS)
#//------------------------------------------------------------------------
#// Figure out how to pull accessibility libs.
#// If no ACCESSIBLE_CO_TAG is specified, use the default tag
#//------------------------------------------------------------------------
!ifndef ACCESSIBLE_CO_FLAGS
ACCESSIBLE_CO_FLAGS=$(MOZ_CO_FLAGS)
!endif
ACCESSIBLE_CO_FLAGS=$(ACCESSIBLE_CO_FLAGS) $(CVS_BRANCH)
CVSCO_ACCESSIBLE = cvs $(CVS_FLAGS) co $(ACCESSIBLE_CO_FLAGS)
#//------------------------------------------------------------------------
#// Figure out how to pull new image library.
#// If no IMGLIB2_CO_TAG is specified, use the default tag
#//------------------------------------------------------------------------
!ifndef IMGLIB2_CO_FLAGS
IMGLIB2_CO_FLAGS=$(MOZ_CO_FLAGS)
!endif
IMGLIB2_CO_FLAGS=$(IMGLIB2_CO_FLAGS) $(CVS_BRANCH)
CVSCO_IMGLIB2 = cvs $(CVS_FLAGS) co $(IMGLIB2_CO_FLAGS)
#//------------------------------------------------------------------------
#// Figure out how to pull new image library.
#// If no GFX2_CO_TAG is specified, use the default tag
#//------------------------------------------------------------------------
!ifndef GFX2_CO_FLAGS
GFX2_CO_FLAGS=$(MOZ_CO_FLAGS)
!endif
GFX2_CO_FLAGS=$(GFX2_CO_FLAGS) $(CVS_BRANCH)
CVSCO_GFX2 = cvs $(CVS_FLAGS) co $(GFX2_CO_FLAGS)
#//------------------------------------------------------------------------
#// Figure out how to pull the internal libart
#// (only pulled and built if MOZ_INTERNAL_LIBART_LGPL is set)
#// If no MOZ_INTERNAL_LIBART_CO_TAG is specified, use the default tag
#//------------------------------------------------------------------------
!if defined(MOZ_SVG) && !defined(MOZ_INTERNAL_LIBART_LGPL)
ERR_MESSAGE = ^
You are trying to build Mozilla with SVG support (MOZ_SVG=1), but you ^
haven not specified that mozilla/other-licenses/libart_lgpl should be ^
pulled and built. At the moment Mozilla SVG builds need this patched ^
version of libart. You either need to disable SVG support (unset MOZ_SVG) ^
or enable pulling and building by setting MOZ_INTERNAL_LIBART_LGPL=1.^
^
If you choose to pull and build libart, note that it is only licensed^
under the terms of the LGPL, not the MPL. (Which is why you have to opt^
in explicitly.)
!endif
!if defined(MOZ_INTERNAL_LIBART_LGPL)
!ifndef MOZ_INTERNAL_LIBART_CO_FLAGS
MOZ_INTERNAL_LIBART_CO_FLAGS=$(MOZ_CO_FLAGS)
!endif
!if "$(MOZ_INTERNAL_LIBART_CO_TAG)" != ""
MOZ_INTERNAL_LIBART_CO_FLAGS=$(MOZ_INTERNAL_LIBART_CO_FLAGS) -r $(MOZ_INTERNAL_LIBART_CO_TAG)
!else
MOZ_INTERNAL_LIBART_CO_FLAGS=$(MOZ_INTERNAL_LIBART_CO_FLAGS) $(CVS_BRANCH)
!endif
CVSCO_MOZ_INTERNAL_LIBART = cvs $(CVS_FLAGS) co $(MOZ_INTERNAL_LIBART_CO_FLAGS)
!endif
## The master target
############################################################
pull_and_build_all: pull_all build_all_dep
## Rules for pulling the source from the cvs repository
############################################################
pull_clobber_and_build_all: pull_all clobber_all build_all
!if !defined(MOZ_INTERNAL_LIBART_LGPL)
pull_all: pull_nspr pull_psm pull_ldapcsdk pull_accessible pull_gfx2 pull_imglib2 pull_seamonkey
!else
pull_all: pull_nspr pull_psm pull_ldapcsdk pull_accessible pull_gfx2 pull_imglib2 pull_moz_internal_libart pull_seamonkey
!endif
pull_nspr: pull_clientmak
cd $(MOZ_SRC)\.
$(CVSCO_NSPR) mozilla/nsprpub
pull_nss:
cd $(MOZ_SRC)\.
$(CVSCO_NSS) mozilla/security/coreconf
$(CVSCO_NSS) mozilla/security/nss
pull_psm: pull_nss
cd $(MOZ_SRC)\.
$(CVSCO_PSM) mozilla/security/manager
$(CVSCO_PSM) mozilla/security/makefile.win
pull_ldapcsdk:
cd $(MOZ_SRC)\.
$(CVSCO_LDAPCSDK) mozilla/directory/c-sdk
pull_accessible:
cd $(MOZ_SRC)\.
$(CVSCO_ACCESSIBLE) mozilla/accessible
pull_gfx2:
cd $(MOZ_SRC)\.
$(CVSCO_GFX2) mozilla/gfx2
pull_imglib2:
cd $(MOZ_SRC)\.
$(CVSCO_IMGLIB2) mozilla/modules/libpr0n
!if defined(MOZ_INTERNAL_LIBART_LGPL)
pull_moz_internal_libart:
cd $(MOZ_SRC)\.
$(CVSCO_MOZ_INTERNAL_LIBART) mozilla/other-licenses/libart_lgpl
!endif
pull_xpconnect: pull_nspr
cd $(MOZ_SRC)\.
$(CVSCO) mozilla/include
$(CVSCO) mozilla/config
$(CVSCO) -l mozilla/js
$(CVSCO) -l mozilla/js/src
$(CVSCO) mozilla/js/src/fdlibm
$(CVSCO) mozilla/js/src/xpconnect
$(CVSCO) mozilla/modules/libreg
$(CVSCO) mozilla/xpcom
$(CVSCO) mozilla/string
# pull either layout only or seamonkey the browser
pull_layout:
cd $(MOZ_SRC)\.
$(CVSCO) RaptorWin
pull_seamonkey: pull_clientmak
cd $(MOZ_SRC)\.
$(CVSCO) SeaMonkeyAll
pull_clientmak:
cd $(MOZ_SRC)\.
$(CVSCO) mozilla/client.mak
############################################################
# nmake has to be hardcoded, or we have to depend on mozilla/config
# being pulled already to figure out what $(NMAKE) should be.
clobber_all: clobber_nspr clobber_ldapcsdk clobber_psm clobber_seamonkey
build_all: build_nspr build_ldapcsdk build_seamonkey
build_all_dep: depend libs
distclean:
@cd $(MOZ_SRC)\$(MOZ_TOP)\directory\c-sdk
gmake -f gmakefile.win distclean MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
gmake -f gmakefile.win distclean MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
@cd $(MOZ_SRC)\$(MOZ_TOP)
nmake /f client.mak clobber_psm
nmake /f client.mak clobber_seamonkey
clobber_ldapcsdk:
@cd $(MOZ_SRC)\$(MOZ_TOP)\directory\c-sdk
gmake -f gmakefile.win clobber_all MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED) \
SHELL=sh
clobber_nspr:
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
gmake -f gmakefile.win clobber_all MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
clobber_psm:
@cd $(MOZ_SRC)\$(MOZ_TOP)\security
nmake -f makefile.win clobber_all
clobber_xpconnect:
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
-rd /s /q dist
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
gmake -f gmakefile.win clobber_all MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
@cd $(MOZ_SRC)\$(MOZ_TOP)\include
nmake -f makefile.win clobber_all
@cd $(MOZ_SRC)\$(MOZ_TOP)\modules\libreg
nmake -f makefile.win clobber_all
@cd $(MOZ_SRC)\$(MOZ_TOP)\string
nmake -f makefile.win clobber_all
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
nmake -f makefile.win clobber_all
@cd $(MOZ_SRC)\$(MOZ_TOP)\js
nmake -f makefile.win clobber_all
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src\xpconnect
nmake -f makefile.win clobber_all
clobber_seamonkey:
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
-rd /s /q dist
nmake -f makefile.win clobber_all
depend: export
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
nmake -f makefile.win depend
depend_xpconnect:
@cd $(MOZ_SRC)\$(MOZ_TOP)\include
nmake -f makefile.win depend
@cd $(MOZ_SRC)\$(MOZ_TOP)\modules\libreg
nmake -f makefile.win depend
@cd $(MOZ_SRC)\$(MOZ_TOP)\string
nmake -f makefile.win depend
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
nmake -f makefile.win depend
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src
nmake -f makefile.win depend
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src\xpconnect
nmake -f makefile.win depend
build_nspr:
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
gmake -f gmakefile.win MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
build_ldapcsdk:
@cd $(MOZ_SRC)\$(MOZ_TOP)\directory\c-sdk
gmake -f gmakefile.win MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED) SHELL=sh
build_psm:
@cd $(MOZ_SRC)\$(MOZ_TOP)\security
nmake -f makefile.win
build_xpconnect: build_nspr
@cd $(MOZ_SRC)\$(MOZ_TOP)\include
nmake -f makefile.win all
@cd $(MOZ_SRC)\$(MOZ_TOP)\modules\libreg
nmake -f makefile.win all
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
nmake -f makefile.win export
@cd $(MOZ_SRC)\$(MOZ_TOP)\string
nmake -f makefile.win all
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
nmake -f makefile.win libs
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src
nmake -f makefile.win all
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src\xpconnect
nmake -f makefile.win all
build_seamonkey:
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
nmake -f makefile.win all
build_client:
@cd $(MOZ_SRC)\mozilla\.
nmake -f makefile.win all
build_layout:
@cd $(MOZ_SRC)\mozilla\.
nmake -f makefile.win all
build_dist:
@cd $(MOZ_SRC)\mozilla\.
nmake -f makefile.win all
libs:
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
nmake -f makefile.win libs
export: build_nspr build_ldapcsdk
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
nmake -f makefile.win export
clobber_dist:
@cd $(MOZ_SRC)\mozilla\.
nmake -f makefile.win clobber_all
clobber_client:
@cd $(MOZ_SRC)\mozilla\.
nmake -f makefile.win clobber_all
clobber_layout:
@cd $(MOZ_SRC)\mozilla\.
nmake -f makefile.win clobber_all
browse_info::
cd $(MOZ_SRC)\$(MOZ_TOP)
-dir /s /b *.sbr > sbrlist.tmp
-bscmake /Es /o mozilla.bsc @sbrlist.tmp
-rm sbrlist.tmp
regchrome::
@cd $(MOZ_SRC)\mozilla\.
nmake /f makefile.win regchrome
deliver::
@cd $(MOZ_SRC)\mozilla\.
nmake /f makefile.win splitsymbols
#//------------------------------------------------------------------------
#// Utility stuff...
#//------------------------------------------------------------------------
#//------------------------------------------------------------------------
# Verify that MOZ_SRC is set correctly
#//------------------------------------------------------------------------
# Check to see if it is set at all
!if "$(MOZ_SRC)"==""
MOZ_SRC = $(MAKEDIR)\..
!endif
#
# create a temp file at the root and make sure it is visible from MOZ_SRC
#
!if [copy $(MAKEDIR)\client.mak $(MAKEDIR)\xyzzy.tmp > NUL] == 0
!endif
!if !EXIST( $(MOZ_SRC)\mozilla\xyzzy.tmp )
ERR_MESSAGE=$(ERR_MESSAGE)^
MOZ_SRC isn't set correctly: [$(MOZ_SRC)\mozilla]!=[$(MAKEDIR)]
!endif
!if [del $(MAKEDIR)\xyzzy.tmp]
!endif
#//------------------------------------------------------------------------
# Verify that MOZ_BITS is set
#//------------------------------------------------------------------------
!if !defined(MOZ_BITS)
ERR_MESSAGE=$(ERR_MESSAGE)^
Environment variable MOZ_BITS isn't set.
!endif
!if !defined(MOZ_TOOLS)
ERR_MESSAGE=$(ERR_MESSAGE)^
Environment variable MOZ_TOOLS isn't set.
!endif
#//------------------------------------------------------------------------
#// Display error
#//------------------------------------------------------------------------
!if "$(ERR_MESSAGE)" != ""
ERR_MESSAGE = ^
client.mak: ^
$(ERR_MESSAGE) ^
^
client.mak: usage^
^
nmake -f client.mak [MOZ_BRANCH=<cvs_branch_name>] ^
[MOZ_DATE=<cvs_date>]^
[pull_and_build_all]^
[pull_all]^
[build_all]^
^
Environment variables:^
^
MOZ_BITS set to 32^
MOZ_TOOLS set to the directory containing the needed tools ^
!ERROR $(ERR_MESSAGE)
!endif

View File

@@ -1,650 +0,0 @@
# 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 Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Stephen Lamm
# Build the Mozilla client.
#
# This needs CVSROOT set to work, e.g.,
# setenv CVSROOT :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
# or
# setenv CVSROOT :pserver:username%somedomain.org@cvs.mozilla.org:/cvsroot
#
# To checkout and build a tree,
# 1. cvs co mozilla/client.mk
# 2. cd mozilla
# 3. gmake -f client.mk
#
# Other targets (gmake -f client.mk [targets...]),
# checkout
# build
# clean (realclean is now the same as clean)
# distclean
#
# See http://www.mozilla.org/build/unix.html for more information.
#
# Options:
# MOZ_OBJDIR - Destination object directory
# MOZ_CO_DATE - Date tag to use for checkout (default: none)
# MOZ_CO_MODULE - Module to checkout (default: SeaMonkeyAll)
# MOZ_CVS_FLAGS - Flags to pass cvs (default: -q -z3)
# MOZ_CO_FLAGS - Flags to pass after 'cvs co' (default: -P)
# MOZ_MAKE_FLAGS - Flags to pass to $(MAKE)
# MOZ_CO_BRANCH - Branch tag (Deprecated. Use MOZ_CO_TAG below.)
#
#######################################################################
# Checkout Tags
#
# For branches, uncomment the MOZ_CO_TAG line with the proper tag,
# and commit this file on that tag.
MOZ_CO_TAG = NETSCAPE_7_0_RTM
NSPR_CO_TAG = NETSCAPE_7_0_RTM
PSM_CO_TAG = NETSCAPE_7_0_RTM
NSS_CO_TAG = NETSCAPE_7_0_RTM
LDAPCSDK_CO_TAG = NETSCAPE_7_0_RTM
ACCESSIBLE_CO_TAG = NETSCAPE_7_0_RTM
GFX2_CO_TAG = NETSCAPE_7_0_RTM
IMGLIB2_CO_TAG = NETSCAPE_7_0_RTM
BUILD_MODULES = all
#######################################################################
# Defines
#
CVS = cvs
CWD := $(shell pwd)
ifeq "$(CWD)" "/"
CWD := /.
endif
ifneq (, $(wildcard client.mk))
# Ran from mozilla directory
ROOTDIR := $(shell dirname $(CWD))
TOPSRCDIR := $(CWD)
else
# Ran from mozilla/.. directory (?)
ROOTDIR := $(CWD)
TOPSRCDIR := $(CWD)/mozilla
endif
# on os2, TOPSRCDIR may have two forward slashes in a row, which doesn't
# work; replace first instance with one forward slash
TOPSRCDIR := $(shell echo "$(TOPSRCDIR)" | sed -e 's%//%/%')
ifndef TOPSRCDIR_MOZ
TOPSRCDIR_MOZ=$(TOPSRCDIR)
endif
# if ROOTDIR equals only drive letter (i.e. "C:"), set to "/"
DIRNAME := $(shell echo "$(ROOTDIR)" | sed -e 's/^.://')
ifeq ($(DIRNAME),)
ROOTDIR := /.
endif
AUTOCONF := autoconf
MKDIR := mkdir
SH := /bin/sh
ifndef MAKE
MAKE := gmake
endif
CONFIG_GUESS_SCRIPT := $(wildcard $(TOPSRCDIR)/build/autoconf/config.guess)
ifdef CONFIG_GUESS_SCRIPT
CONFIG_GUESS = $(shell $(CONFIG_GUESS_SCRIPT))
else
_IS_FIRST_CHECKOUT := 1
endif
####################################
# CVS
# Add the CVS root to CVS_FLAGS if needed
CVS_ROOT_IN_TREE := $(shell cat $(TOPSRCDIR)/CVS/Root 2>/dev/null)
ifneq ($(CVS_ROOT_IN_TREE),)
ifneq ($(CVS_ROOT_IN_TREE),$(CVSROOT))
CVS_FLAGS := -d $(CVS_ROOT_IN_TREE)
endif
endif
CVSCO = $(strip $(CVS) $(CVS_FLAGS) co $(CVS_CO_FLAGS))
CVSCO_LOGFILE := $(ROOTDIR)/cvsco.log
CVSCO_LOGFILE := $(shell echo $(CVSCO_LOGFILE) | sed s%//%/%)
ifdef MOZ_CO_TAG
CVS_CO_FLAGS := -r $(MOZ_CO_TAG)
endif
####################################
# Load mozconfig Options
# See build pages, http://www.mozilla.org/build/unix.html,
# for how to set up mozconfig.
MOZCONFIG_LOADER := mozilla/build/autoconf/mozconfig2client-mk
MOZCONFIG_FINDER := mozilla/build/autoconf/mozconfig-find
MOZCONFIG_MODULES := mozilla/build/unix/modules.mk
run_for_side_effects := \
$(shell cd $(ROOTDIR); \
if test "$(_IS_FIRST_CHECKOUT)"; then \
$(CVSCO) $(MOZCONFIG_FINDER) $(MOZCONFIG_LOADER) $(MOZCONFIG_MODULES); \
else true; \
fi; \
$(MOZCONFIG_LOADER) $(TOPSRCDIR) mozilla/.mozconfig.mk > mozilla/.mozconfig.out)
include $(TOPSRCDIR)/.mozconfig.mk
include $(TOPSRCDIR)/build/unix/modules.mk
####################################
# Options that may come from mozconfig
# Change CVS flags if anonymous root is requested
ifdef MOZ_CO_USE_MIRROR
CVS_FLAGS := -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
endif
# MOZ_CVS_FLAGS - Basic CVS flags
ifeq "$(origin MOZ_CVS_FLAGS)" "undefined"
CVS_FLAGS := $(CVS_FLAGS) -q -z 3
else
CVS_FLAGS := $(MOZ_CVS_FLAGS)
endif
# This option is deprecated. The best way to have client.mk pull a tag
# is to set MOZ_CO_TAG (see above) and commit that change on the tag.
ifdef MOZ_CO_BRANCH
$(warning Use MOZ_CO_TAG instead of MOZ_CO_BRANCH)
CVS_CO_FLAGS := -r $(MOZ_CO_BRANCH)
endif
# MOZ_CO_FLAGS - Anything that we should use on all checkouts
ifeq "$(origin MOZ_CO_FLAGS)" "undefined"
CVS_CO_FLAGS := $(CVS_CO_FLAGS) -P
else
CVS_CO_FLAGS := $(CVS_CO_FLAGS) $(MOZ_CO_FLAGS)
endif
ifdef MOZ_CO_DATE
CVS_CO_DATE_FLAGS := -D "$(MOZ_CO_DATE)"
endif
ifdef MOZ_OBJDIR
OBJDIR := $(MOZ_OBJDIR)
MOZ_MAKE := $(MAKE) $(MOZ_MAKE_FLAGS) -C $(OBJDIR)
else
OBJDIR := $(TOPSRCDIR)
MOZ_MAKE := $(MAKE) $(MOZ_MAKE_FLAGS)
endif
####################################
# CVS defines for PSM
#
PSM_CO_MODULE= mozilla/security/manager
PSM_CO_FLAGS := -P -A
ifdef MOZ_CO_FLAGS
PSM_CO_FLAGS := $(MOZ_CO_FLAGS)
endif
ifdef PSM_CO_TAG
PSM_CO_FLAGS := $(PSM_CO_FLAGS) -r $(PSM_CO_TAG)
endif
CVSCO_PSM = $(CVS) $(CVS_FLAGS) co $(PSM_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(PSM_CO_MODULE)
####################################
# CVS defines for NSS
#
NSS_CO_MODULE = mozilla/security/nss \
mozilla/security/coreconf \
$(NULL)
NSS_CO_FLAGS := -P
ifdef MOZ_CO_FLAGS
NSS_CO_FLAGS := $(MOZ_CO_FLAGS)
endif
ifdef NSS_CO_TAG
NSS_CO_FLAGS := $(NSS_CO_FLAGS) -r $(NSS_CO_TAG)
endif
# Cannot pull static tags by date
ifeq ($(NSS_CO_TAG),NSS_CLIENT_TAG)
CVSCO_NSS = $(CVS) $(CVS_FLAGS) co $(NSS_CO_FLAGS) $(NSS_CO_MODULE)
else
CVSCO_NSS = $(CVS) $(CVS_FLAGS) co $(NSS_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(NSS_CO_MODULE)
endif
####################################
# CVS defines for NSPR
#
NSPR_CO_MODULE = mozilla/nsprpub
NSPR_CO_FLAGS := -P
ifdef MOZ_CO_FLAGS
NSPR_CO_FLAGS := $(MOZ_CO_FLAGS)
endif
ifdef NSPR_CO_TAG
NSPR_CO_FLAGS := $(NSPR_CO_FLAGS) -r $(NSPR_CO_TAG)
endif
# Cannot pull static tags by date
ifeq ($(NSPR_CO_TAG),NSPRPUB_CLIENT_TAG)
CVSCO_NSPR = $(CVS) $(CVS_FLAGS) co $(NSPR_CO_FLAGS) $(NSPR_CO_MODULE)
else
CVSCO_NSPR = $(CVS) $(CVS_FLAGS) co $(NSPR_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(NSPR_CO_MODULE)
endif
####################################
# CVS defines for the C LDAP SDK
#
LDAPCSDK_CO_MODULE = mozilla/directory/c-sdk
LDAPCSDK_CO_FLAGS := -P
ifdef MOZ_CO_FLAGS
LDAPCSDK_CO_FLAGS := $(MOZ_CO_FLAGS)
endif
ifdef LDAPCSDK_CO_TAG
LDAPCSDK_CO_FLAGS := $(LDAPCSDK_CO_FLAGS) -r $(LDAPCSDK_CO_TAG)
endif
CVSCO_LDAPCSDK = $(CVS) $(CVS_FLAGS) co $(LDAPCSDK_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(LDAPCSDK_CO_MODULE)
####################################
# CVS defines for the C LDAP SDK
#
ACCESSIBLE_CO_MODULE = mozilla/accessible
ACCESSIBLE_CO_FLAGS := -P
ifdef MOZ_CO_FLAGS
ACCESSIBLE_CO_FLAGS := $(MOZ_CO_FLAGS)
endif
ifdef ACCESSIBLE_CO_TAG
ACCESSIBLE_CO_FLAGS := $(ACCESSIBLE_CO_FLAGS) -r $(ACCESSIBLE_CO_TAG)
endif
CVSCO_ACCESSIBLE = $(CVS) $(CVS_FLAGS) co $(ACCESSIBLE_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(ACCESSIBLE_CO_MODULE)
####################################
# CVS defines for gfx2
#
GFX2_CO_MODULE = mozilla/gfx2
GFX2_CO_FLAGS := -P
ifdef MOZ_CO_FLAGS
GFX2_CO_FLAGS := $(MOZ_CO_FLAGS)
endif
ifdef GFX2_CO_TAG
GFX2_CO_FLAGS := $(GFX2_CO_FLAGS) -r $(GFX2_CO_TAG)
endif
CVSCO_GFX2 = $(CVS) $(CVS_FLAGS) co $(GFX2_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(GFX2_CO_MODULE)
####################################
# CVS defines for new image library
#
IMGLIB2_CO_MODULE = mozilla/modules/libpr0n
IMGLIB2_CO_FLAGS := -P
ifdef MOZ_CO_FLAGS
IMGLIB2_CO_FLAGS := $(MOZ_CO_FLAGS)
endif
ifdef IMGLIB2_CO_TAG
IMGLIB2_CO_FLAGS := $(IMGLIB2_CO_FLAGS) -r $(IMGLIB2_CO_TAG)
endif
CVSCO_IMGLIB2 = $(CVS) $(CVS_FLAGS) co $(IMGLIB2_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(IMGLIB2_CO_MODULE)
####################################
# CVS defines for standalone modules
#
ifneq ($(BUILD_MODULES),all)
MOZ_CO_MODULE := $(filter-out $(NSPRPUB_DIR) security directory/c-sdk, $(BUILD_MODULE_CVS))
MOZ_CO_MODULE += allmakefiles.sh client.mk aclocal.m4 configure configure.in
MOZ_CO_MODULE += Makefile.in
MOZ_CO_MODULE := $(addprefix mozilla/, $(MOZ_CO_MODULE))
NOSUBDIRS_MODULE := $(addprefix mozilla/, $(BUILD_MODULE_CVS_NS))
ifneq ($(NOSUBDIRS_MODULE),)
CVSCO_NOSUBDIRS := $(CVSCO) -l $(CVS_CO_DATE_FLAGS) $(NOSUBDIRS_MODULE)
endif
ifeq (,$(filter $(NSPRPUB_DIR), $(BUILD_MODULE_CVS)))
CVSCO_NSPR :=
endif
ifeq (,$(filter security security/manager, $(BUILD_MODULE_CVS)))
CVSCO_PSM :=
CVSCO_NSS :=
endif
ifeq (,$(filter directory/c-sdk, $(BUILD_MODULE_CVS)))
CVSCO_LDAPCSDK :=
endif
ifeq (,$(filter accessible, $(BUILD_MODULE_CVS)))
CVSCO_ACCESSIBLE :=
endif
ifeq (,$(filter gfx2, $(BUILD_MODULE_CVS)))
CVSCO_GFX2 :=
endif
ifeq (,$(filter modules/libpr0n, $(BUILD_MODULE_CVS)))
CVSCO_IMGLIB2 :=
endif
endif
####################################
# CVS defines for SeaMonkey
#
ifeq ($(MOZ_CO_MODULE),)
MOZ_CO_MODULE := SeaMonkeyAll
endif
CVSCO_SEAMONKEY := $(CVSCO) $(CVS_CO_DATE_FLAGS) $(MOZ_CO_MODULE)
####################################
# CVS defined for libart (pulled and built if MOZ_INTERNAL_LIBART_LGPL is set)
#
CVSCO_LIBART := $(CVSCO) $(CVS_CO_DATE_FLAGS) mozilla/other-licenses/libart_lgpl
ifdef MOZ_INTERNAL_LIBART_LGPL
FASTUPDATE_LIBART := fast_update $(CVSCO_LIBART)
CHECKOUT_LIBART := cvs_co $(CVSCO_LIBART)
else
CHECKOUT_LIBART := true
FASTUPDATE_LIBART := true
endif
####################################
# CVS defines for Calendar (pulled and built if MOZ_CALENDAR is set)
#
CVSCO_CALENDAR := $(CVSCO) $(CVS_CO_DATE_FLAGS) mozilla/calendar
ifdef MOZ_CALENDAR
FASTUPDATE_CALENDAR := fast_update $(CVSCO_CALENDAR)
CHECKOUT_CALENDAR := cvs_co $(CVSCO_CALENDAR)
else
CHECKOUT_CALENDAR := true
FASTUPDATE_CALENDAR := true
endif
# because some cygwin tools can't handle native dos-drive paths & vice-versa
# force configure to use a relative path for --srcdir
# need a better check for win32
# and we need to get OBJDIR earlier
ifdef MOZ_TOOLS
_tmpobjdir := $(shell cygpath -u $(OBJDIR))
_abs2rel := $(shell cygpath -w $(TOPSRCDIR)/build/unix/abs2rel.pl | sed -e 's|\\|/|g')
_OBJ2SRCPATH := $(shell $(_abs2rel) $(TOPSRCDIR) $(_tmpobjdir))
endif
#######################################################################
# Rules
#
# Print out any options loaded from mozconfig.
all build checkout clean depend distclean export libs install realclean::
@if test -f .mozconfig.out; then \
cat .mozconfig.out; \
rm -f .mozconfig.out; \
else true; \
fi
ifdef _IS_FIRST_CHECKOUT
all:: checkout build
else
all:: checkout alldep
endif
# Windows equivalents
pull_all: checkout
build_all: build
build_all_dep: alldep
build_all_depend: alldep
clobber clobber_all: clean
pull_and_build_all: checkout alldep
# Do everything from scratch
everything: checkout clean build
####################################
# CVS checkout
#
checkout::
# @: Backup the last checkout log.
@if test -f $(CVSCO_LOGFILE) ; then \
mv $(CVSCO_LOGFILE) $(CVSCO_LOGFILE).old; \
else true; \
fi
ifdef RUN_AUTOCONF_LOCALLY
@echo "Removing local configures" ; \
cd $(ROOTDIR) && \
$(RM) -f mozilla/configure mozilla/nsprpub/configure \
mozilla/directory/c-sdk/configure
endif
@echo "checkout start: "`date` | tee $(CVSCO_LOGFILE)
@echo '$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk'; \
cd $(ROOTDIR) && \
$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk
@cd $(ROOTDIR) && $(MAKE) -f mozilla/client.mk real_checkout
real_checkout:
# @: Start the checkout. Split the output to the tty and a log file. \
# : If it fails, touch an error file because "tee" hides the error.
@failed=.cvs-failed.tmp; rm -f $$failed*; \
cvs_co() { echo "$$@" ; \
("$$@" || touch $$failed) 2>&1 | tee -a $(CVSCO_LOGFILE) && \
if test -f $$failed; then false; else true; fi; }; \
cvs_co $(CVSCO_NSPR) && \
cvs_co $(CVSCO_NSS) && \
cvs_co $(CVSCO_PSM) && \
cvs_co $(CVSCO_LDAPCSDK) && \
cvs_co $(CVSCO_ACCESSIBLE) && \
cvs_co $(CVSCO_GFX2) && \
cvs_co $(CVSCO_IMGLIB2) && \
$(CHECKOUT_CALENDAR) && \
$(CHECKOUT_LIBART) && \
cvs_co $(CVSCO_SEAMONKEY) && \
cvs_co $(CVSCO_NOSUBDIRS)
@echo "checkout finish: "`date` | tee -a $(CVSCO_LOGFILE)
# @: Check the log for conflicts. ;
@conflicts=`egrep "^C " $(CVSCO_LOGFILE)` ;\
if test "$$conflicts" ; then \
echo "$(MAKE): *** Conflicts during checkout." ;\
echo "$$conflicts" ;\
echo "$(MAKE): Refer to $(CVSCO_LOGFILE) for full log." ;\
false; \
else true; \
fi
ifdef RUN_AUTOCONF_LOCALLY
@echo Generating configures using $(AUTOCONF) ; \
cd $(TOPSRCDIR) && $(AUTOCONF) && \
cd $(TOPSRCDIR)/nsprpub && $(AUTOCONF) && \
cd $(TOPSRCDIR)/directory/c-sdk && $(AUTOCONF)
endif
fast-update:
# @: Backup the last checkout log.
@if test -f $(CVSCO_LOGFILE) ; then \
mv $(CVSCO_LOGFILE) $(CVSCO_LOGFILE).old; \
else true; \
fi
ifdef RUN_AUTOCONF_LOCALLY
@echo "Removing local configures" ; \
cd $(ROOTDIR) && \
$(RM) -f mozilla/configure mozilla/nsprpub/configure \
mozilla/directory/c-sdk/configure
endif
@echo "checkout start: "`date` | tee $(CVSCO_LOGFILE)
@echo '$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk'; \
cd $(ROOTDIR) && \
$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk
@cd $(TOPSRCDIR) && \
$(MAKE) -f client.mk real_fast-update
real_fast-update:
# @: Start the update. Split the output to the tty and a log file. \
# : If it fails, touch an error file because "tee" hides the error.
@failed=.fast_update-failed.tmp; rm -f $$failed*; \
fast_update() { (config/cvsco-fast-update.pl $$@ || touch $$failed) 2>&1 | tee -a $(CVSCO_LOGFILE) && \
if test -f $$failed; then false; else true; fi; }; \
cvs_co() { echo "$$@" ; \
("$$@" || touch $$failed) 2>&1 | tee -a $(CVSCO_LOGFILE) && \
if test -f $$failed; then false; else true; fi; }; \
fast_update $(CVSCO_NSPR) && \
cd $(ROOTDIR) && \
failed=mozilla/.fast_update-failed.tmp && \
cvs_co $(CVSCO_NSS) && \
failed=.fast_update-failed.tmp && \
cd mozilla && \
fast_update $(CVSCO_PSM) && \
fast_update $(CVSCO_LDAPCSDK) && \
fast_update $(CVSCO_ACCESSIBLE) && \
fast_update $(CVSCO_GFX2) && \
fast_update $(CVSCO_IMGLIB2) && \
$(FASTUPDATE_CALENDAR) && \
$(FASTUPDATE_LIBART) && \
fast_update $(CVSCO_SEAMONKEY) && \
fast_update $(CVSCO_NOSUBDIRS)
@echo "fast_update finish: "`date` | tee -a $(CVSCO_LOGFILE)
# @: Check the log for conflicts. ;
@conflicts=`egrep "^C " $(CVSCO_LOGFILE)` ;\
if test "$$conflicts" ; then \
echo "$(MAKE): *** Conflicts during fast-update." ;\
echo "$$conflicts" ;\
echo "$(MAKE): Refer to $(CVSCO_LOGFILE) for full log." ;\
false; \
else true; \
fi
ifdef RUN_AUTOCONF_LOCALLY
@echo Generating configures using $(AUTOCONF) ; \
cd $(TOPSRCDIR) && $(AUTOCONF) && \
cd $(TOPSRCDIR)/nsprpub && $(AUTOCONF) && \
cd $(TOPSRCDIR)/directory/c-sdk && $(AUTOCONF)
endif
####################################
# Web configure
WEBCONFIG_FILE := $(HOME)/.mozconfig
MOZCONFIG2CONFIGURATOR := build/autoconf/mozconfig2configurator
webconfig:
@cd $(TOPSRCDIR); \
url=`$(MOZCONFIG2CONFIGURATOR) $(TOPSRCDIR)`; \
echo Running mozilla with the following url: ;\
echo ;\
echo $$url ;\
mozilla -remote "openURL($$url)" || \
netscape -remote "openURL($$url)" || \
mozilla $$url || \
netscape $$url ;\
echo ;\
echo 1. Fill out the form on the browser. ;\
echo 2. Save the results to $(WEBCONFIG_FILE)
#####################################################
# First Checkout
ifdef _IS_FIRST_CHECKOUT
# First time, do build target in a new process to pick up new files.
build::
$(MAKE) -f $(TOPSRCDIR)/client.mk build
else
#####################################################
# After First Checkout
####################################
# Configure
CONFIG_STATUS := $(wildcard $(OBJDIR)/config.status)
CONFIG_CACHE := $(wildcard $(OBJDIR)/config.cache)
ifdef RUN_AUTOCONF_LOCALLY
EXTRA_CONFIG_DEPS := \
$(TOPSRCDIR)/aclocal.m4 \
$(wildcard $(TOPSRCDIR)/build/autoconf/*.m4) \
$(NULL)
$(TOPSRCDIR)/configure: $(TOPSRCDIR)/configure.in $(EXTRA_CONFIG_DEPS)
@echo Generating $@ using autoconf
cd $(TOPSRCDIR); $(AUTOCONF)
endif
CONFIG_STATUS_DEPS_L10N := $(wildcard $(TOPSRCDIR)/l10n/makefiles.all)
CONFIG_STATUS_DEPS := \
$(TOPSRCDIR)/configure \
$(TOPSRCDIR)/allmakefiles.sh \
$(TOPSRCDIR)/.mozconfig.mk \
$(wildcard $(TOPSRCDIR)/nsprpub/configure) \
$(wildcard $(TOPSRCDIR)/directory/c-sdk/configure) \
$(wildcard $(TOPSRCDIR)/mailnews/makefiles) \
$(CONFIG_STATUS_DEPS_L10N) \
$(wildcard $(TOPSRCDIR)/themes/makefiles) \
$(NULL)
# configure uses the program name to determine @srcdir@. Calling it without
# $(TOPSRCDIR) will set @srcdir@ to "."; otherwise, it is set to the full
# path of $(TOPSRCDIR).
ifeq ($(TOPSRCDIR),$(OBJDIR))
CONFIGURE := ./configure
else
CONFIGURE := $(TOPSRCDIR)/configure
endif
ifdef _OBJ2SRCPATH
CONFIGURE_ARGS := --srcdir=$(_OBJ2SRCPATH) $(CONFIGURE_ARGS)
endif
$(OBJDIR)/Makefile $(OBJDIR)/config.status: $(CONFIG_STATUS_DEPS)
@if test ! -d $(OBJDIR); then $(MKDIR) $(OBJDIR); else true; fi
@echo cd $(OBJDIR);
@echo $(CONFIGURE) $(CONFIGURE_ARGS)
@cd $(OBJDIR) && $(CONFIGURE_ENV_ARGS) $(CONFIGURE) $(CONFIGURE_ARGS) \
|| ( echo "*** Fix above errors and then restart with\
\"$(MAKE) -f client.mk build\"" && exit 1 )
@touch $(OBJDIR)/Makefile
ifdef CONFIG_STATUS
$(OBJDIR)/config/autoconf.mk: $(TOPSRCDIR)/config/autoconf.mk.in
cd $(OBJDIR); \
CONFIG_FILES=config/autoconf.mk ./config.status
endif
####################################
# Depend
depend:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
$(MOZ_MAKE) export && $(MOZ_MAKE) depend
####################################
# Build it
build:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
$(MOZ_MAKE)
####################################
# Other targets
# Pass these target onto the real build system
install export libs clean realclean distclean alldep:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
$(MOZ_MAKE) $@
cleansrcdir:
@cd $(TOPSRCDIR); \
if [ -f webshell/embed/gtk/Makefile ]; then \
$(MAKE) -C webshell/embed/gtk distclean; \
fi; \
if [ -f Makefile ]; then \
$(MAKE) distclean ; \
else \
echo "Removing object files from srcdir..."; \
rm -fr `find . -type d \( -name .deps -print -o -name CVS \
-o -exec test ! -d {}/CVS \; \) -prune \
-o \( -name '*.[ao]' -o -name '*.so' \) -type f -print`; \
build/autoconf/clean-config.sh; \
fi;
# (! IS_FIRST_CHECKOUT)
endif
.PHONY: checkout real_checkout depend build export libs alldep install clean realclean distclean cleansrcdir pull_all build_all clobber clobber_all pull_and_build_all everything

View File

@@ -0,0 +1,129 @@
/* -*- Mode: C++; tab-width: 2; 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) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
/******
This file contains the list of all XUL nsIAtoms and their values
It is designed to be used as inline input to nsXULAtoms.cpp *only*
through the magic of C preprocessing.
All entires must be enclosed in the macro XUL_ATOM which will have cruel
and unusual things done to it
It is recommended (but not strictly necessary) to keep all entries
in alphabetical order
The first argument to XUL_ATOM is the C++ identifier of the atom
The second argument is the string value of the atom
******/
XUL_ATOM(button, "button")
XUL_ATOM(spinner, "spinner")
XUL_ATOM(scrollbar, "scrollbar")
XUL_ATOM(slider, "slider")
XUL_ATOM(colorpicker, "colorpicker")
XUL_ATOM(palettename, "palettename")
XUL_ATOM(fontpicker, "fontpicker")
XUL_ATOM(radio, "radio")
XUL_ATOM(text, "text")
XUL_ATOM(toolbar, "toolbar")
XUL_ATOM(toolbaritem, "toolbaritem")
XUL_ATOM(toolbox, "toolbox")
// The tree atoms
XUL_ATOM(tree, "tree") // The start of a tree view
XUL_ATOM(treecaption, "treecaption") // The caption of a tree view
XUL_ATOM(treehead, "treehead") // The header of the tree view
XUL_ATOM(treerow, "treerow") // A row in the tree view
XUL_ATOM(treecell, "treecell") // An item in the tree view
XUL_ATOM(treeitem, "treeitem") // A cell in the tree view
XUL_ATOM(treechildren, "treechildren") // The children of an item in the tree view
XUL_ATOM(treeindentation, "treeindentation") // Specifies that the indentation for the level should occur here.
XUL_ATOM(allowevents, "allowevents") // Lets events be handled on the cell contents or in menus.
XUL_ATOM(treecol, "treecol") // A column in the tree view
XUL_ATOM(treecolgroup, "treecolgroup") // A column group in the tree view
XUL_ATOM(treefoot, "treefoot") // The footer of the tree view
XUL_ATOM(treepusher, "treepusher") // A column pusher (left or right) for the tree view
XUL_ATOM(scrollbarlist, "scrollbarlist") // An atom for internal use by the tree view
XUL_ATOM(open, "open") // Whether or not a menu, tree, etc. is open
XUL_ATOM(menubar, "menubar") // An XP menu bar.
XUL_ATOM(menu, "menu") // Represents an XP menu
XUL_ATOM(menuitem, "menuitem") // Represents an XP menu item
XUL_ATOM(menupopup, "menupopup") // The XP menu's children.
XUL_ATOM(menuactive, "menuactive") // Whether or not a menu is active (without necessarily being open)
XUL_ATOM(accesskey, "accesskey") // The shortcut key for a menu or menu item
XUL_ATOM(acceltext, "acceltext") // Text to use for the accelerator
XUL_ATOM(popupset, "popupset") // Contains popup menus, context menus, and tooltips
XUL_ATOM(popup, "popup") // The popup for a context menu, popup menu, or tooltip
XUL_ATOM(menugenerated, "menugenerated") // Internal
XUL_ATOM(key, "key") // A key element
XUL_ATOM(broadcaster, "broadcaster") // A broadcaster
XUL_ATOM(observes, "observes") // The observes element
XUL_ATOM(templateAtom, "template") // A XUL template
XUL_ATOM(progressmeter, "progressmeter")
XUL_ATOM(titledbutton, "titledbutton")
XUL_ATOM(crop, "crop")
XUL_ATOM(mode, "mode")
XUL_ATOM(box, "box")
XUL_ATOM(flex, "flex")
XUL_ATOM(spring, "spring")
XUL_ATOM(deck, "deck")
XUL_ATOM(tabcontrol, "tabcontrol")
XUL_ATOM(tab, "tab")
XUL_ATOM(tabpanel, "tabpanel")
XUL_ATOM(tabpage, "tabpage")
XUL_ATOM(tabbox, "tabbox")
XUL_ATOM(index, "index")
XUL_ATOM(maxpos, "maxpos")
XUL_ATOM(curpos, "curpos")
XUL_ATOM(scrollbarbutton, "scrollbarbutton")
XUL_ATOM(increment, "increment")
XUL_ATOM(pageincrement, "pageincrement")
XUL_ATOM(thumb, "thumb")
XUL_ATOM(toggled, "toggled")
XUL_ATOM(grippy, "grippy")
XUL_ATOM(splitter, "splitter")
XUL_ATOM(collapse, "collapse")
XUL_ATOM(resizebefore, "resizebefore")
XUL_ATOM(resizeafter, "resizeafter")
XUL_ATOM(state, "state")
// toolbar & toolbar d&d atoms
XUL_ATOM(tbDropLocation, "tb-droplocation")
XUL_ATOM(tbDropLocationCoord, "tb-droplocationcoord")
XUL_ATOM(tbDropOn, "tb-dropon")
XUL_ATOM(tbTriggerRepaint, "tb-triggerrepaint")
XUL_ATOM(container, "container")
XUL_ATOM(widget, "widget")
XUL_ATOM(window, "window")
XUL_ATOM(iframe, "iframe")
XUL_ATOM(browser, "browser")
XUL_ATOM(editor, "editor")

View File

@@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
#ifndef nsXULAtoms_h___
#define nsXULAtoms_h___
#include "prtypes.h"
#include "nsIAtom.h"
class nsINameSpaceManager;
/**
* This class wraps up the creation and destruction of the standard
* set of xul atoms used during normal xul handling. This object
* is created when the first xul content object is created, and
* destroyed when the last such content object is destroyed.
*/
class nsXULAtoms {
public:
static void AddRefAtoms();
static void ReleaseAtoms();
// XUL namespace ID, good for the life of the nsXULAtoms object
static PRInt32 nameSpaceID;
/* Declare all atoms
The atom names and values are stored in nsCSSAtomList.h and
are brought to you by the magic of C preprocessing
Add new atoms to nsCSSAtomList and all support logic will be auto-generated
*/
#define XUL_ATOM(_name, _value) static nsIAtom* _name;
#include "nsXULAtomList.h"
#undef XUL_ATOM
};
#endif /* nsXULAtoms_h___ */

View File

@@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
#include "nsString.h"
#include "nsINameSpaceManager.h"
#include "nsXULAtoms.h"
static const char kXULNameSpace[] = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
PRInt32 nsXULAtoms::nameSpaceID;
// define storage for all atoms
#define XUL_ATOM(_name, _value) nsIAtom* nsXULAtoms::_name;
#include "nsXULAtomList.h"
#undef XUL_ATOM
static nsrefcnt gRefCnt = 0;
static nsINameSpaceManager* gNameSpaceManager;
void nsXULAtoms::AddRefAtoms() {
if (gRefCnt == 0) {
/* XUL Atoms registers the XUL name space ID because it's a convenient
place to do this, if you don't want a permanent, "well-known" ID.
*/
if (NS_SUCCEEDED(NS_NewNameSpaceManager(&gNameSpaceManager))) {
// gNameSpaceManager->CreateRootNameSpace(namespace);
nsAutoString nameSpace(kXULNameSpace);
gNameSpaceManager->RegisterNameSpace(nameSpace, nameSpaceID);
} else {
NS_ASSERTION(0, "failed to create xul atoms namespace manager");
}
// now register the atoms
#define XUL_ATOM(_name, _value) _name = NS_NewAtom(_value);
#include "nsXULAtomList.h"
#undef XUL_ATOM
}
++gRefCnt;
}
void nsXULAtoms::ReleaseAtoms() {
NS_PRECONDITION(gRefCnt != 0, "bad release of xul atoms");
if (--gRefCnt == 0) {
#define XUL_ATOM(_name, _value) NS_RELEASE(_name);
#include "nsXULAtomList.h"
#undef XUL_ATOM
NS_IF_RELEASE(gNameSpaceManager);
}
}

View File

@@ -0,0 +1,28 @@
#
# 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.
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = content base
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,28 @@
#
# 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.
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,22 @@
#!nmake
#
# 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.
DEPTH=..\..\..
DIRS=public src
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,31 @@
#
# 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.
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = layout
EXPORTS = nsIPopupSetFrame.h
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,2 @@
nsIPopupSetFrame.h

View File

@@ -0,0 +1,26 @@
#!nmake
#
# 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.
DEPTH=..\..\..\..
EXPORTS = \
nsIPopupSetFrame.h \
$(NULL)
MODULE=raptor
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,52 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsIMenuParent_h___
#define nsIMenuParent_h___
// {D407BF61-3EFA-11d3-97FA-00400553EEF0}
#define NS_IMENUPARENT_IID \
{ 0xd407bf61, 0x3efa, 0x11d3, { 0x97, 0xfa, 0x0, 0x40, 0x5, 0x53, 0xee, 0xf0 } }
class nsIMenuFrame;
class nsIMenuParent : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IMENUPARENT_IID; return iid; }
NS_IMETHOD SetCurrentMenuItem(nsIMenuFrame* aMenuItem) = 0;
NS_IMETHOD GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult) = 0;
NS_IMETHOD GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult) = 0;
NS_IMETHOD SetActive(PRBool aActiveFlag) = 0;
NS_IMETHOD GetIsActive(PRBool& isActive) = 0;
NS_IMETHOD GetWidget(nsIWidget **aWidget) = 0;
NS_IMETHOD IsMenuBar(PRBool& isMenuBar) = 0;
NS_IMETHOD DismissChain() = 0;
NS_IMETHOD HideChain() = 0;
NS_IMETHOD CreateDismissalListener() = 0;
};
#endif

View File

@@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsIPopupSetFrame_h___
#define nsIPopupSetFrame_h___
// {E2D804A1-50CA-11d3-BF87-00105A1B0627}
#define NS_IPOPUPSETFRAME_IID \
{ 0xe2d804a1, 0x50ca, 0x11d3, { 0xbf, 0x87, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 } }
class nsIFrame;
class nsIContent;
#include "nsString.h"
class nsIPopupSetFrame : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IPOPUPSETFRAME_IID; return iid; }
NS_IMETHOD CreatePopup(nsIFrame* aElementFrame, nsIContent* aPopupContent,
PRInt32 aXPos, PRInt32 aYPos,
const nsString& aPopupType, const nsString& anAnchorAlignment,
const nsString& aPopupAlignment) = 0;
NS_IMETHOD HidePopup() = 0;
NS_IMETHOD DestroyPopup() = 0;
};
#endif

View File

@@ -0,0 +1,85 @@
#
# 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.
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = layout
LIBRARY_NAME = raptorxulbase_s
CPPSRCS = \
nsFrameNavigator.cpp \
nsSplitterFrame.cpp \
nsGrippyFrame.cpp \
nsTabFrame.cpp \
nsDeckFrame.cpp \
nsBoxFrame.cpp \
nsProgressMeterFrame.cpp \
nsTitledButtonFrame.cpp \
nsToolbarFrame.cpp \
nsToolbarDragListener.cpp \
nsToolboxFrame.cpp \
nsTreeOuterFrame.cpp \
nsTreeFrame.cpp \
nsTreeRowGroupFrame.cpp \
nsTreeIndentationFrame.cpp \
nsTreeCellFrame.cpp \
nsTreeRowFrame.cpp \
nsTreeTwistyListener.cpp \
nsSpinnerFrame.cpp \
nsScrollbarFrame.cpp \
nsScrollbarButtonFrame.cpp \
nsSliderFrame.cpp \
nsColorPickerFrame.cpp \
nsStdColorPicker.cpp \
nsFontPickerFrame.cpp \
nsToolbarItemFrame.cpp \
nsMenuPopupFrame.cpp \
nsMenuFrame.cpp \
nsMenuBarFrame.cpp \
nsMenuBarListener.cpp \
nsMenuDismissalListener.cpp \
nsPopupSetFrame.cpp \
nsRepeatService.cpp \
$(NULL)
include $(topsrcdir)/config/config.mk
# we don't want the shared lib, but we want to force the creation of a static lib.
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk
DEFINES += -D_IMPL_NS_HTML
LOCAL_INCLUDES = \
-I$(srcdir)/../../../base/src \
-I$(srcdir)/../../../html/table/src \
-I$(srcdir)/../../../html/style/src \
-I$(srcdir)/../../../html/base/src \
-I$(srcdir)/../../../html/forms/src \
-I$(srcdir)/../../content/src \
-I$(srcdir)/../../../html/content/src \
-I$(srcdir)/../../../xml/content/src \
-I$(srcdir)/../../../base/public \
$(NULL)

View File

@@ -0,0 +1,123 @@
#!nmake
#
# 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.
DEPTH=..\..\..\..
LIBRARY_NAME=raptorxulbase_s
MODULE=raptor
REQUIRES=xpcom raptor pref
DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN
CPPSRCS= \
nsFrameNavigator.cpp \
nsRepeatService.cpp \
nsToolbarDragListener.cpp \
nsToolbarItemFrame.cpp \
nsSplitterFrame.cpp \
nsGrippyFrame.cpp \
nsTabFrame.cpp \
nsDeckFrame.cpp \
nsBoxFrame.cpp \
nsProgressMeterFrame.cpp \
nsTitledButtonFrame.cpp \
nsToolboxFrame.cpp \
nsToolbarFrame.cpp \
nsTreeOuterFrame.cpp \
nsTreeFrame.cpp \
nsTreeRowGroupFrame.cpp \
nsTreeRowFrame.cpp \
nsTreeIndentationFrame.cpp \
nsTreeCellFrame.cpp \
nsTreeTwistyListener.cpp \
nsSpinnerFrame.cpp \
nsScrollbarFrame.cpp \
nsScrollbarButtonFrame.cpp \
nsSliderFrame.cpp \
nsColorPickerFrame.cpp \
nsStdColorPicker.cpp \
nsFontPickerFrame.cpp \
nsMenuPopupFrame.cpp \
nsMenuFrame.cpp \
nsMenuBarFrame.cpp \
nsMenuBarListener.cpp \
nsMenuDismissalListener.cpp \
nsPopupSetFrame.cpp \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsFrameNavigator.obj \
.\$(OBJDIR)\nsRepeatService.obj \
.\$(OBJDIR)\nsToolbarDragListener.obj \
.\$(OBJDIR)\nsToolbarItemFrame.obj \
.\$(OBJDIR)\nsGrippyFrame.obj \
.\$(OBJDIR)\nsSplitterFrame.obj \
.\$(OBJDIR)\nsTabFrame.obj \
.\$(OBJDIR)\nsDeckFrame.obj \
.\$(OBJDIR)\nsBoxFrame.obj \
.\$(OBJDIR)\nsProgressMeterFrame.obj \
.\$(OBJDIR)\nsTitledButtonFrame.obj \
.\$(OBJDIR)\nsToolboxFrame.obj \
.\$(OBJDIR)\nsToolbarFrame.obj \
.\$(OBJDIR)\nsTreeOuterFrame.obj \
.\$(OBJDIR)\nsTreeFrame.obj \
.\$(OBJDIR)\nsTreeRowFrame.obj \
.\$(OBJDIR)\nsTreeRowGroupFrame.obj \
.\$(OBJDIR)\nsTreeIndentationFrame.obj \
.\$(OBJDIR)\nsTreeCellFrame.obj \
.\$(OBJDIR)\nsTreeTwistyListener.obj \
.\$(OBJDIR)\nsSpinnerFrame.obj \
.\$(OBJDIR)\nsScrollbarFrame.obj \
.\$(OBJDIR)\nsScrollbarButtonFrame.obj \
.\$(OBJDIR)\nsSliderFrame.obj \
.\$(OBJDIR)\nsColorPickerFrame.obj \
.\$(OBJDIR)\nsStdColorPicker.obj \
.\$(OBJDIR)\nsFontPickerFrame.obj \
.\$(OBJDIR)\nsMenuPopupFrame.obj \
.\$(OBJDIR)\nsMenuFrame.obj \
.\$(OBJDIR)\nsMenuBarFrame.obj \
.\$(OBJDIR)\nsMenuBarListener.obj \
.\$(OBJDIR)\nsMenuDismissalListener.obj \
.\$(OBJDIR)\nsPopupSetFrame.obj \
$(NULL)
EXPORTS = \
$(NULL)
LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\js \
-I..\..\..\html\style\src -I..\..\..\html\base\src -I$(PUBLIC)\dom \
-I..\..\..\html\document\src \
-I..\..\..\html\content\src \
-I..\..\..\html\table\src \
-I..\..\content\src \
-I..\..\..\html\forms\src \
-I$(PUBLIC)\netlib -I..\..\..\base\src -I$(PUBLIC)\pref \
-I..\..\..\xml\content\src \
-I..\..\..\base\public
LCFLAGS = \
$(LCFLAGS) \
$(DEFINES) \
$(NULL)
include <$(DEPTH)\config\rules.mak>
libs:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,196 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
/**
Eric D Vaughan
nsBoxFrame is a frame that can lay its children out either vertically or horizontally.
It lays them out according to a min max or preferred size.
**/
#ifndef nsBoxFrame_h___
#define nsBoxFrame_h___
#include "nsCOMPtr.h"
#include "nsHTMLContainerFrame.h"
#include "nsIBox.h"
#include "nsISpaceManager.h"
class nsBoxFrameInner;
class nsBoxDebugInner;
class nsHTMLReflowCommand;
class nsCalculatedBoxInfo : public nsBoxInfo {
public:
nsSize calculatedSize;
PRBool prefWidthIntrinsic;
PRBool prefHeightIntrinsic;
PRBool sizeValid;
PRBool needsReflow;
PRBool needsRecalc;
PRBool collapsed;
PRBool isIncremental;
nsCalculatedBoxInfo();
nsCalculatedBoxInfo(const nsBoxInfo& aInfo);
virtual void clear();
};
class nsBoxFrame : public nsHTMLContainerFrame, public nsIBox
{
public:
friend nsresult NS_NewBoxFrame(nsIFrame** aNewFrame, PRUint32 aFlags = 0);
// gets the rect inside our border and debug border. If you wish to paint inside a box
// call this method to get the rect so you don't draw on the debug border or outer border.
virtual void GetInnerRect(nsRect& aInner);
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame);
NS_IMETHOD GetCursor(nsIPresContext& aPresContext,
nsPoint& aPoint,
PRInt32& aCursor);
// nsIBox methods
NS_IMETHOD GetBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize);
NS_IMETHOD Dirty(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& aIncrementalChild);
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* asPrevInFlow);
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint);
NS_IMETHOD Paint ( nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame);
NS_IMETHOD GetFrameName(nsString& aResult) const;
virtual PRBool IsHorizontal() const { return mHorizontal; }
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
virtual ~nsBoxFrame();
virtual void GetChildBoxInfo(PRInt32 aIndex, nsBoxInfo& aSize);
virtual void SetChildNeedsRecalc(PRInt32 aIndex, PRBool aRecalc);
// Paint one child frame
virtual void PaintChild(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsIFrame* aFrame,
nsFramePaintLayer aWhichLayer);
protected:
nsBoxFrame(PRUint32 aFlags = 0);
virtual void GetRedefinedMinPrefMax(nsIPresContext& aPresContext, nsIFrame* aFrame, nsCalculatedBoxInfo& aSize);
virtual nsresult GetChildBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame* aFrame, nsCalculatedBoxInfo& aSize);
virtual nsresult FlowChildren(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
nsRect& availableSize);
virtual nsresult FlowChildAt(nsIFrame* frame,
nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
nsCalculatedBoxInfo& aInfo,
PRBool& needsRedraw,
nsString& aReason);
virtual nsresult PlaceChildren(nsIPresContext& aPresContext, nsRect& boxRect);
virtual void ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nsCalculatedBoxInfo& aInfo, PRBool* aResized, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason);
virtual void LayoutChildrenInRect(nsRect& size);
virtual void AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo);
virtual void BoundsCheck(const nsBoxInfo& aBoxInfo, nsRect& aRect);
virtual void InvalidateChildren();
virtual void AddSize(const nsSize& a, nsSize& b, PRBool largest);
virtual PRIntn GetSkipSides() const { return 0; }
virtual void GetInset(nsMargin& margin);
virtual void CollapseChild(nsIPresContext& aPresContext, nsIFrame* frame, PRBool hide);
nsresult GenerateDirtyReflowCommand(nsIPresContext& aPresContext,
nsIPresShell& aPresShell);
PRBool mHorizontal;
nsCalculatedBoxInfo mSprings[100];
nscoord mSpringCount;
private:
friend class nsBoxFrameInner;
friend class nsBoxDebugInner;
nsBoxFrameInner* mInner;
}; // class nsBoxFrame
#endif

View File

@@ -0,0 +1,27 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
// 1936f892-1dd2-11b2-aba4-bd254241f938
#define NS_DEFCOLORPICKER_CID \
{ 0x1936f892, 0x1dd2, 0x11b2, \
{0xab, 0xa4, 0xbd, 0x25, 0x42, 0x41, 0xf9, 0x38} }

View File

@@ -0,0 +1,230 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
#include "nsColorPickerFrame.h"
#include "nsIDOMElement.h"
#include "nsIContent.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsHTMLAtoms.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsCSSRendering.h"
#include "nsINameSpaceManager.h"
#include "nsColor.h"
#include "nsIServiceManager.h"
#include "nsStdColorPicker.h"
#include "nsColorPickerCID.h"
//
// NS_NewColorPickerFrame
//
// Wrapper for creating a new color picker
//
nsresult
NS_NewColorPickerFrame(nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsColorPickerFrame* it = new nsColorPickerFrame;
if ( !it )
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
}
// static NS_DEFINE_IID(kDefColorPickerCID, NS_DEFCOLORPICKER_CID);
//
// nsColorPickerFrame cntr
//
nsColorPickerFrame::nsColorPickerFrame()
{
}
nsColorPickerFrame::~nsColorPickerFrame()
{
delete mColorPicker;
}
NS_IMETHODIMP
nsColorPickerFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsLeafFrame::Init(aPresContext, aContent, aParent, aContext,
aPrevInFlow);
nsAutoString type;
mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, type);
if (type.EqualsIgnoreCase("swatch") || type.Equals(""))
{
mColorPicker = new nsStdColorPicker();
mColorPicker->Init(mContent);
}
return rv;
}
NS_IMETHODIMP
nsColorPickerFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
aEventStatus = nsEventStatus_eConsumeDoDefault;
if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN)
HandleMouseDownEvent(aPresContext, aEvent, aEventStatus);
return NS_OK;
}
nsresult
nsColorPickerFrame::HandleMouseDownEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
int x,y;
char *color;
// figure out what color we just picked
#ifdef DEBUG_pavlov
printf("got mouse down.. x = %i, y = %i\n", aEvent->refPoint.x, aEvent->refPoint.y);
#endif
x = aEvent->refPoint.x;
y = aEvent->refPoint.y;
nsCOMPtr<nsIDOMElement> node( do_QueryInterface(mContent) );
nsresult rv = mColorPicker->GetColor(x, y, &color);
if (NS_FAILED(rv))
node->RemoveAttribute("color");
else
node->SetAttribute("color", color);
return NS_OK;
}
//
// Paint
//
//
NS_METHOD
nsColorPickerFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
float p2t;
aPresContext.GetScaledPixelsToTwips(&p2t);
const nsStyleDisplay* disp = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
// if we aren't visible then we are done.
if (!disp->mVisible)
return NS_OK;
// if we are visible then tell our superclass to paint
nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer);
// get our border
const nsStyleSpacing* spacing = (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
nsMargin border(0,0,0,0);
spacing->CalcBorderFor(this, border);
/*
const nsStyleColor* colorStyle = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color);
nscolor color = colorStyle->mColor;
*/
aRenderingContext.PushState();
// set the clip region
PRInt32 width, height;
mColorPicker->GetSize(&width, &height);
nsRect rect(0, 0, PRInt32(width*p2t), PRInt32(height*p2t));
PRBool clipState;
// Clip so we don't render outside the inner rect
aRenderingContext.SetClipRect(rect, nsClipCombine_kIntersect, clipState);
// call the color picker's paint method
mColorPicker->Paint(&aPresContext, &aRenderingContext);
aRenderingContext.PopState(clipState);
return NS_OK;
}
//
// GetDesiredSize
//
// For now, be as big as CSS wants us to be, or some small default size.
//
void
nsColorPickerFrame::GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize)
{
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
// if the width is set use it
if (NS_INTRINSICSIZE != aReflowState.mComputedWidth)
aDesiredSize.width = aReflowState.mComputedWidth;
else
aDesiredSize.width = -1;
// if the height is set use it
if (NS_INTRINSICSIZE != aReflowState.mComputedHeight)
aDesiredSize.height = aReflowState.mComputedHeight;
else
aDesiredSize.height = -1;
mColorPicker->SetSize((aDesiredSize.width == -1) ? -1 : PRInt32(aDesiredSize.width/p2t),
(aDesiredSize.height == -1) ? -1 : PRInt32(aDesiredSize.height/p2t));
int width, height;
mColorPicker->GetSize(&width, &height);
aDesiredSize.width = nscoord(width * p2t);
aDesiredSize.height = nscoord(height * p2t);
aDesiredSize.ascent = nscoord(height * p2t);
aDesiredSize.descent = 0;
} // GetDesiredSize

View File

@@ -0,0 +1,81 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
//
// nsColorPickerFrame
//
#ifndef nsColorPickerFrame_h__
#define nsColorPickerFrame_h__
#include "nsLeafFrame.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsCOMPtr.h"
#include "nsIColorPicker.h"
class nsString;
nsresult NS_NewColorPickerFrame(nsIFrame** aResult) ;
class nsColorPickerFrame : public nsLeafFrame
{
public:
nsColorPickerFrame();
virtual ~nsColorPickerFrame();
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const {
return MakeFrameName("ColorPickerFrame", aResult);
}
#endif
// nsIFrame overrides
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
nsresult HandleMouseDownEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
protected:
virtual void GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize) ;
private:
nsIColorPicker *mColorPicker;
}; // class nsColorPickerFrame
#endif

View File

@@ -0,0 +1,363 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
#include "nsDeckFrame.h"
#include "nsIStyleContext.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
#include "nsCOMPtr.h"
#include "nsHTMLIIDs.h"
#include "nsUnitConversion.h"
#include "nsINameSpaceManager.h"
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsIReflowCommand.h"
#include "nsHTMLParts.h"
#include "nsIPresShell.h"
#include "nsStyleChangeList.h"
#include "nsCSSRendering.h"
#include "nsIViewManager.h"
nsresult
NS_NewDeckFrame ( nsIFrame** aNewFrame )
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsDeckFrame* it = new nsDeckFrame;
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
} // NS_NewDeckFrame
NS_IMETHODIMP
nsDeckFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
// Get the element's tag
nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
//CreateViewForFrame(aPresContext,this,aContext,PR_TRUE);
return rv;
}
NS_IMETHODIMP
nsDeckFrame::AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint)
{
nsresult rv = nsBoxFrame::AttributeChanged(aPresContext, aChild,
aNameSpaceID, aAttribute, aHint);
// if the index changed hide the old element and make the now element visible
if (aAttribute == nsHTMLAtoms::index) {
/*
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
nsCOMPtr<nsIReflowCommand> reflowCmd;
rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), this,
nsIReflowCommand::StyleChanged);
if (NS_SUCCEEDED(rv))
shell->AppendReflowCommand(reflowCmd);
*/
Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE);
int index = 0;
// get the index attribute
nsAutoString value;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::index, value))
{
PRInt32 error;
// convert it to an integer
index = value.ToInteger(&error);
}
nsIFrame* childFrame = mFrames.FirstChild();
nscoord count = 0;
while (nsnull != childFrame)
{
// make collapsed children not show up
if (index != count)
CollapseChild(*aPresContext, childFrame, PR_TRUE);
else
CollapseChild(*aPresContext, childFrame, PR_FALSE);
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
}
}
if (NS_OK != rv) {
return rv;
}
return NS_OK;
}
nsIFrame*
nsDeckFrame::GetSelectedFrame()
{
// ok we want to paint only the child that as at the given index
// default index is 0
int index = 0;
// get the index attribute
nsAutoString value;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::index, value))
{
PRInt32 error;
// convert it to an integer
index = value.ToInteger(&error);
}
// get the child at that index.
nsIFrame* childFrame = mFrames.FrameAt(index);
return childFrame;
}
NS_IMETHODIMP
nsDeckFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
// if a tab is hidden all its children are too.
const nsStyleDisplay* disp = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
if (!disp->mVisible)
return NS_OK;
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
if (disp->mVisible && mRect.width && mRect.height) {
// Paint our background and border
PRIntn skipSides = GetSkipSides();
const nsStyleColor* color = (const nsStyleColor*)
mStyleContext->GetStyleData(eStyleStruct_Color);
const nsStyleSpacing* spacing = (const nsStyleSpacing*)
mStyleContext->GetStyleData(eStyleStruct_Spacing);
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *color, *spacing, 0, 0);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *spacing, mStyleContext, skipSides);
}
}
nsIFrame* frame = GetSelectedFrame();
if (frame != nsnull)
PaintChild(aPresContext, aRenderingContext, aDirtyRect, frame, aWhichLayer);
return NS_OK;
}
NS_IMETHODIMP nsDeckFrame::GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame)
{
// if its not in our child just return us.
*aFrame = this;
// get the selected frame and see if the point is in it.
nsIFrame* selectedFrame = GetSelectedFrame();
if (nsnull != selectedFrame)
{
nsRect childRect;
selectedFrame->GetRect(childRect);
if (childRect.Contains(aPoint)) {
// adjust the point
nsPoint p = aPoint;
p.x -= childRect.x;
p.y -= childRect.y;
return selectedFrame->GetFrameForPoint(aPresContext, p, aFrame);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDeckFrame::SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsresult r = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList);
return r;
}
void
nsDeckFrame::AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo)
{
// largest preferred size
if (aChildInfo.prefSize.width > aInfo.prefSize.width)
aInfo.prefSize.width = aChildInfo.prefSize.width;
if (aChildInfo.prefSize.height > aInfo.prefSize.height)
aInfo.prefSize.height = aChildInfo.prefSize.height;
// largest min size
if (aChildInfo.minSize.width > aInfo.minSize.width)
aInfo.minSize.width = aChildInfo.minSize.width;
if (aChildInfo.minSize.height > aInfo.minSize.height)
aInfo.minSize.height = aChildInfo.minSize.height;
// smallest max size
if (aChildInfo.maxSize.width < aInfo.maxSize.width)
aInfo.maxSize.width = aChildInfo.maxSize.width;
if (aChildInfo.maxSize.height < aInfo.maxSize.height)
aInfo.maxSize.height = aChildInfo.maxSize.height;
}
nsresult
nsDeckFrame::PlaceChildren(nsIPresContext& aPresContext, nsRect& boxRect)
{
// ------- set the childs positions ---------
nsIFrame* childFrame = mFrames.FirstChild();
nscoord count = 0;
while (nsnull != childFrame)
{
nsresult rv;
// make collapsed children not show up
if (mSprings[count].collapsed) {
//nsRect rect(0,0,0,0);
//childFrame->GetRect(rect);
//if (rect.width > 0 || rect.height > 0) {
// childFrame->SizeTo(0,0);
CollapseChild(aPresContext, childFrame, PR_TRUE);
//}
} else {
childFrame->MoveTo(&aPresContext, boxRect.x, boxRect.y);
}
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
}
return NS_OK;
}
NS_IMETHODIMP
nsDeckFrame::DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus)
{
int index = 0;
// get the index attribute
nsAutoString value;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::index, value))
{
PRInt32 error;
// convert it to an integer
index = value.ToInteger(&error);
}
nsresult rv = nsBoxFrame::DidReflow(aPresContext, aStatus);
NS_ASSERTION(rv == NS_OK,"DidReflow failed");
nsIFrame* childFrame = mFrames.FirstChild();
nscoord count = 0;
while (nsnull != childFrame)
{
// make collapsed children not show up
if (index != count)
CollapseChild(aPresContext, childFrame, PR_TRUE);
else
CollapseChild(aPresContext, childFrame, PR_FALSE);
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
}
return rv;
}
void
nsDeckFrame::ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nsCalculatedBoxInfo& aInfo, PRBool* aResized, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason)
{
if (aDesiredSize.width > aRect.width) {
aRect.width = aDesiredSize.width;
InvalidateChildren();
LayoutChildrenInRect(aRect);
aReason = "child's width got bigger";
aChangedIndex = aIndex;
aFinished = PR_FALSE;
} else if (aDesiredSize.height > aRect.height) {
aRect.height = aDesiredSize.height;
InvalidateChildren();
LayoutChildrenInRect(aRect);
aReason = "child's height got bigger";
aChangedIndex = aIndex;
aFinished = PR_FALSE;
}
}
void
nsDeckFrame::LayoutChildrenInRect(nsRect& size)
{
for (int i=0; i<mSpringCount; i++) {
mSprings[i].calculatedSize.width = size.width;
mSprings[i].calculatedSize.height = size.height;
mSprings[i].sizeValid = PR_TRUE;
}
}

View File

@@ -0,0 +1,93 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
/**
Eric D Vaughan
A frame that can have multiple children. Only one child may be displayed at one time. So the
can be flipped though like a deck of cards.
**/
#ifndef nsDeckFrame_h___
#define nsDeckFrame_h___
#include "nsBoxFrame.h"
class nsDeckFrame : public nsBoxFrame
{
public:
friend nsresult NS_NewDeckFrame(nsIFrame** aNewFrame);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* asPrevInFlow);
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint);
NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus);
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame);
virtual PRIntn GetSkipSides() const { return 0; }
protected:
virtual nsIFrame* GetSelectedFrame();
virtual nsresult PlaceChildren(nsIPresContext& aPresContext, nsRect& boxRect);
virtual void ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nsCalculatedBoxInfo& aInfo, PRBool* aResized, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason);
virtual void LayoutChildrenInRect(nsRect& size);
virtual void AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo);
private:
nsIFrame* mSelected;
}; // class nsDeckFrame
#endif

View File

@@ -0,0 +1,111 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
#include "nsFontPickerFrame.h"
#include "nsIContent.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsCSSRendering.h"
#include "nsINameSpaceManager.h"
//
// NS_NewFontPickerFrame
//
// Wrapper for creating a new font picker
//
nsresult
NS_NewFontPickerFrame(nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsFontPickerFrame* it = new nsFontPickerFrame;
if ( !it )
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
}
//
// nsFontPickerFrame cntr
//
nsFontPickerFrame::nsFontPickerFrame()
{
} // cntr
//
// Paint
//
// Overidden to handle ???
//
NS_METHOD
nsFontPickerFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
return nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
}
//
// GetDesiredSize
//
// For now, be as big as CSS wants us to be, or some small default size.
//
void
nsFontPickerFrame :: GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredLayoutSize)
{
const int CSS_NOTSET = -1;
nsSize styleSize;
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
styleSize.width = aReflowState.mComputedWidth;
}
else {
styleSize.width = CSS_NOTSET;
}
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) {
styleSize.height = aReflowState.mComputedHeight;
}
else {
styleSize.height = CSS_NOTSET;
}
// subclasses should always override this method, but if not and no css, make it small
aDesiredLayoutSize.width = (styleSize.width > CSS_NOTSET) ? styleSize.width : 200;
aDesiredLayoutSize.height = (styleSize.height > CSS_NOTSET) ? styleSize.height : 200;
aDesiredLayoutSize.ascent = aDesiredLayoutSize.height;
aDesiredLayoutSize.descent = 0;
if (aDesiredLayoutSize.maxElementSize) {
aDesiredLayoutSize.maxElementSize->width = aDesiredLayoutSize.width;
aDesiredLayoutSize.maxElementSize->height = aDesiredLayoutSize.height;
}
} // GetDesiredSize

View File

@@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
//
// nsFontPickerFrame
//
#ifndef nsFontPickerFrame_h__
#define nsFontPickerFrame_h__
#include "nsLeafFrame.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsCOMPtr.h"
class nsString;
nsresult NS_NewFontPickerFrame(nsIFrame** aResult) ;
class nsFontPickerFrame : public nsLeafFrame
{
public:
nsFontPickerFrame();
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const {
return MakeFrameName("FontPickerFrame", aResult);
}
#endif
// nsIFrame overrides
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
protected:
virtual void GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize) ;
}; // class nsFontPickerFrame
#endif

View File

@@ -0,0 +1,127 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
#include "nsFrameNavigator.h"
#include "nsCOMPtr.h"
#include "nsIContent.h"
nsIAtom*
nsFrameNavigator::GetTag(nsIFrame* frame)
{
nsCOMPtr<nsIContent> content;
frame->GetContent(getter_AddRefs(content));
if (content) {
nsIAtom* atom = nsnull;
content->GetTag(atom);
return atom;
}
return nsnull;
}
nsIFrame*
nsFrameNavigator::GetChildBeforeAfter(nsIFrame* start, PRBool before)
{
nsIFrame* parent = nsnull;
start->GetParent(&parent);
PRInt32 index = IndexOf(parent,start);
PRInt32 count = CountFrames(parent);
if (index == -1)
return nsnull;
if (before) {
if (index == 0) {
return nsnull;
}
return GetChildAt(parent, index-1);
}
if (index == count-1)
return nsnull;
return GetChildAt(parent, index+1);
}
PRInt32
nsFrameNavigator::IndexOf(nsIFrame* parent, nsIFrame* child)
{
PRInt32 count = 0;
nsIFrame* childFrame;
parent->FirstChild(nsnull, &childFrame);
while (nsnull != childFrame)
{
if (childFrame == child)
return count;
nsresult rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
}
return -1;
}
PRInt32
nsFrameNavigator::CountFrames(nsIFrame* aFrame)
{
PRInt32 count = 0;
nsIFrame* childFrame;
aFrame->FirstChild(nsnull, &childFrame);
while (nsnull != childFrame)
{
nsresult rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
}
return count;
}
nsIFrame*
nsFrameNavigator::GetChildAt(nsIFrame* parent, PRInt32 index)
{
PRInt32 count = 0;
nsIFrame* childFrame;
parent->FirstChild(nsnull, &childFrame);
while (nsnull != childFrame)
{
if (count == index)
return childFrame;
nsresult rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
}
return nsnull;
}

View File

@@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
/**
Eric D Vaughan
This class lays out its children either vertically or horizontally
**/
#ifndef nsGrippyFrame_h___
#define nsGrippyFrame_h___
#include "nsIFrame.h"
class nsFrameNavigator
{
public:
static nsIFrame* GetChildBeforeAfter(nsIFrame* start, PRBool before);
static nsIFrame* GetChildAt(nsIFrame* parent, PRInt32 index);
static PRInt32 IndexOf(nsIFrame* parent, nsIFrame* child);
static PRInt32 CountFrames(nsIFrame* aFrame);
static nsIAtom* GetTag(nsIFrame* frame);
};
#endif

View File

@@ -0,0 +1,240 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
#include "nsGrippyFrame.h"
#include "nsScrollbarButtonFrame.h"
#include "nsIStyleContext.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
#include "nsCOMPtr.h"
#include "nsHTMLIIDs.h"
#include "nsUnitConversion.h"
#include "nsINameSpaceManager.h"
#include "nsHTMLAtoms.h"
#include "nsXULAtoms.h"
#include "nsIReflowCommand.h"
//#include "nsSliderFrame.h"
#include "nsIDOMElement.h"
#include "nsIDOMDocument.h"
#include "nsDocument.h"
#include "nsHTMLParts.h"
#include "nsIPresShell.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsHTMLContainerFrame.h"
//
// NS_NewToolbarFrame
//
// Creates a new Toolbar frame and returns it in |aNewFrame|
//
nsresult
NS_NewGrippyFrame ( nsIFrame** aNewFrame )
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsGrippyFrame* it = new nsGrippyFrame;
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
} // NS_NewGrippyFrame
nsGrippyFrame::nsGrippyFrame():mCollapsed(PR_FALSE)
{
}
void
nsGrippyFrame::MouseClicked(nsIPresContext& aPresContext)
{
nsIFrame* splitter;
nsScrollbarButtonFrame::GetParentWithTag(nsXULAtoms::splitter, this, splitter);
if (splitter == nsnull)
return;
// get the splitters content node
nsCOMPtr<nsIContent> content;
splitter->GetContent(getter_AddRefs(content));
nsString a = "collapsed";
nsString value;
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::state, value))
{
if (value=="collapsed")
a = "open";
}
content->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, a, PR_TRUE);
}
/*
void
nsGrippyFrame::MouseClicked(nsIPresContext& aPresContext)
{
nsString style;
if (mCollapsed) {
style = mCollapsedChildStyle;
} else {
// when clicked see if we are in a splitter.
nsIFrame* splitter;
nsScrollbarButtonFrame::GetParentWithTag(nsXULAtoms::splitter, this, splitter);
if (splitter == nsnull)
return;
// get the splitters content node
nsCOMPtr<nsIContent> content;
splitter->GetContent(getter_AddRefs(content));
// get the collapse attribute. If the attribute is not set collapse
// the child before otherwise collapse the child after
PRBool before = PR_TRUE;
nsString value;
if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::collapse, value))
{
if (value=="after")
before = PR_FALSE;
}
// find the child just in the box just before the splitter. If we are not currently collapsed then
// then get the childs style attribute and store it. Then set the child style attribute to be display none.
// if we are already collapsed then set the child's style back to our stored value.
nsIFrame* child = GetChildBeforeAfter(splitter,before);
if (child == nsnull)
return;
child->GetContent(getter_AddRefs(mCollapsedChild));
style = "visibility: collapse";
mCollapsedChildStyle = "";
mCollapsedChild->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::style, mCollapsedChildStyle);
}
mCollapsedChild->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::style, style, PR_TRUE);
mCollapsed = !mCollapsed;
}
*/
nsIFrame*
nsGrippyFrame::GetChildBeforeAfter(nsIFrame* start, PRBool before)
{
nsIFrame* parent = nsnull;
start->GetParent(&parent);
PRInt32 index = IndexOf(parent,start);
PRInt32 count = CountFrames(parent);
if (index == -1)
return nsnull;
if (before) {
if (index == 0) {
return nsnull;
}
return GetChildAt(parent, index-1);
}
if (index == count-1)
return nsnull;
return GetChildAt(parent, index+1);
}
PRInt32
nsGrippyFrame::IndexOf(nsIFrame* parent, nsIFrame* child)
{
PRInt32 count = 0;
nsIFrame* childFrame;
parent->FirstChild(nsnull, &childFrame);
while (nsnull != childFrame)
{
if (childFrame == child)
return count;
nsresult rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
}
return -1;
}
PRInt32
nsGrippyFrame::CountFrames(nsIFrame* aFrame)
{
PRInt32 count = 0;
nsIFrame* childFrame;
aFrame->FirstChild(nsnull, &childFrame);
while (nsnull != childFrame)
{
nsresult rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
}
return count;
}
nsIFrame*
nsGrippyFrame::GetChildAt(nsIFrame* parent, PRInt32 index)
{
PRInt32 count = 0;
nsIFrame* childFrame;
parent->FirstChild(nsnull, &childFrame);
while (nsnull != childFrame)
{
if (count == index)
return childFrame;
nsresult rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
}
return nsnull;
}
NS_IMETHODIMP
nsGrippyFrame::GetFrameName(nsString& aResult) const
{
aResult = "Grippy";
return NS_OK;
}

View File

@@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
/**
Eric D Vaughan
This class lays out its children either vertically or horizontally
**/
#ifndef nsGrippyFrame_h___
#define nsGrippyFrame_h___
#include "nsTitledButtonFrame.h"
#include "nsCOMPtr.h"
#include "nsIContent.h"
class nsGrippyFrame : public nsTitledButtonFrame
{
public:
friend nsresult NS_NewGrippyFrame(nsIFrame** aNewFrame);
NS_IMETHOD GetFrameName(nsString& aResult) const;
static nsIFrame* GetChildBeforeAfter(nsIFrame* start, PRBool before);
static nsIFrame* GetChildAt(nsIFrame* parent, PRInt32 index);
static PRInt32 IndexOf(nsIFrame* parent, nsIFrame* child);
static PRInt32 CountFrames(nsIFrame* aFrame);
nsGrippyFrame();
protected:
virtual void MouseClicked(nsIPresContext& aPresContext);
private:
PRBool mCollapsed;
nsString mCollapsedChildStyle;
nsCOMPtr<nsIContent> mCollapsedChild;
PRBool mDidDrag;
}; // class nsTabFrame
#endif

View File

@@ -0,0 +1,77 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
/**
Eric D Vaughan
nsBoxFrame is a frame that can lay its children out either vertically or horizontally.
It lays them out according to a min max or preferred size.
**/
#ifndef nsIBox_h___
#define nsIBox_h___
class nsIPresContext;
class nsIFrame;
struct nsHTMLReflowState;
class nsBoxInfo;
// {02A560C0-01BF-11d3-B35C-00A0CC3C1CDE}
#define NS_IBOX_IID { 0x2a560c0, 0x1bf, 0x11d3, { 0xb3, 0x5c, 0x0, 0xa0, 0xcc, 0x3c, 0x1c, 0xde } }
static NS_DEFINE_IID(kIBoxIID, NS_IBOX_IID);
class nsBoxInfo {
public:
nsSize prefSize;
nsSize minSize;
nsSize maxSize;
float flex;
nsBoxInfo() { clear(); }
virtual void clear()
{
prefSize.width = 0;
prefSize.height = 0;
minSize.width = 0;
minSize.height = 0;
flex = 0.0;
maxSize.width = NS_INTRINSICSIZE;
maxSize.height = NS_INTRINSICSIZE;
}
};
class nsIBox : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IBOX_IID; return iid; }
NS_IMETHOD GetBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize)=0;
NS_IMETHOD Dirty(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild)=0;
};
#endif

View File

@@ -0,0 +1,77 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef __nsIColorPicker_h__
#define __nsIColorPicker_h__
#include "nsISupports.h"
#include "nsrootidl.h"
#include "nsIPresContext.h"
#include "nsIRenderingContext.h"
/* starting interface: nsIColorPicker */
#define NS_ICOLORPICKER_IID_STR "ed133d04-1dd1-11b2-957f-a04e70608d6e"
#define NS_ICOLORPICKER_IID \
{0xed133d04, 0x1dd1, 0x11b2, \
{ 0x95, 0x7f, 0xa0, 0x4e, 0x70, 0x60, 0x8d, 0x6e }}
class nsIColorPicker : public nsISupports {
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICOLORPICKER_IID)
/* void Init (in nsIContent aContent); */
NS_IMETHOD Init(nsIContent * aContent) = 0;
/* void Paint (in nsIPresContext aPresContext, in nsIRenderingContext aRenderingContext); */
NS_IMETHOD Paint(nsIPresContext * aPresContext, nsIRenderingContext * aRenderingContext) = 0;
/* void GetColor (in PRInt32 aX, in PRInt32 aY, out string aColor); */
NS_IMETHOD GetColor(PRInt32 aX, PRInt32 aY, char **aColor) = 0;
/* void SetColor (in PRInt32 aWidth, in PRInt32 aHeight); */
NS_IMETHOD SetSize(PRInt32 aWidth, PRInt32 aHeight) = 0;
/* void GetSize (out PRInt32 aWidth, out PRInt32 aHeight); */
NS_IMETHOD GetSize(PRInt32 *aWidth, PRInt32 *aHeight) = 0;
};
/* Use this macro when declaring classes that implement this interface. */
#define NS_DECL_NSICOLORPICKER \
NS_IMETHOD Init(nsIContent * aContent); \
NS_IMETHOD Paint(nsIPresContext * aPresContext, nsIRenderingContext * aRenderingContext); \
NS_IMETHOD GetColor(PRInt32 aX, PRInt32 aY, char **aColor); \
NS_IMETHOD SetSize(PRInt32 aWidth, PRInt32 aHeight); \
NS_IMETHOD GetSize(PRInt32 *aWidth, PRInt32 *aHeight);
/* Use this macro to declare functions that forward the behavior of this interface to another object. */
#define NS_FORWARD_NSICOLORPICKER(_to) \
NS_IMETHOD Init(nsIContent * aContent) { return _to ## Init(aContent); } \
NS_IMETHOD Paint(nsIPresContext * aPresContext, nsIRenderingContext * aRenderingContext) { return _to ## Paint(aPresContext, aRenderingContext); } \
NS_IMETHOD GetColor(PRInt32 aX, PRInt32 aY, char **aColor) { return _to ## GetColor(aX, aY, aColor); } \
NS_IMETHOD SetSize(PRInt32 aWidth, PRInt32 aHeight) { return _to ## SetSize(aWidth, aHeight); } \
NS_IMETHOD GetSize(PRInt32 *aWidth, PRInt32 *aHeight) { return _to ## GetSize(aWidth, aHeight); }
#endif /* __nsIColorPicker_h__ */

View File

@@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsIMenuFrame_h___
#define nsIMenuFrame_h___
// {6A4CDE51-6C05-11d3-BB50-00104B7B7DEB}
#define NS_IMENUFRAME_IID \
{ 0x6a4cde51, 0x6c05, 0x11d3, { 0xbb, 0x50, 0x0, 0x10, 0x4b, 0x7b, 0x7d, 0xeb } }
class nsIMenuParent;
enum nsMenuType {
eMenuType_Normal = 0,
eMenuType_Checkbox = 1,
eMenuType_Radio = 2
};
class nsIMenuFrame : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IMENUFRAME_IID; return iid; }
NS_IMETHOD ActivateMenu(PRBool aFlag) = 0;
NS_IMETHOD SelectMenu(PRBool aFlag) = 0;
NS_IMETHOD OpenMenu(PRBool aFlag) = 0;
NS_IMETHOD MenuIsOpen(PRBool& aResult) = 0;
NS_IMETHOD MenuIsContainer(PRBool& aResult) = 0;
NS_IMETHOD MenuIsChecked(PRBool& aResult) = 0;
NS_IMETHOD SelectFirstItem() = 0;
NS_IMETHOD Escape(PRBool& aHandledFlag) = 0;
NS_IMETHOD Enter() = 0;
NS_IMETHOD ShortcutNavigation(PRUint32 aLetter, PRBool& aHandledFlag) = 0;
NS_IMETHOD KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag) = 0;
NS_IMETHOD GetMenuParent(nsIMenuParent** aMenuParent) = 0;
NS_IMETHOD GetRadioGroupName(nsString &aName) = 0;
NS_IMETHOD GetMenuType(nsMenuType &aType) = 0;
NS_IMETHOD MarkAsGenerated() = 0;
};
#endif

View File

@@ -0,0 +1,52 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsIMenuParent_h___
#define nsIMenuParent_h___
// {D407BF61-3EFA-11d3-97FA-00400553EEF0}
#define NS_IMENUPARENT_IID \
{ 0xd407bf61, 0x3efa, 0x11d3, { 0x97, 0xfa, 0x0, 0x40, 0x5, 0x53, 0xee, 0xf0 } }
class nsIMenuFrame;
class nsIMenuParent : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IMENUPARENT_IID; return iid; }
NS_IMETHOD SetCurrentMenuItem(nsIMenuFrame* aMenuItem) = 0;
NS_IMETHOD GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult) = 0;
NS_IMETHOD GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult) = 0;
NS_IMETHOD SetActive(PRBool aActiveFlag) = 0;
NS_IMETHOD GetIsActive(PRBool& isActive) = 0;
NS_IMETHOD GetWidget(nsIWidget **aWidget) = 0;
NS_IMETHOD IsMenuBar(PRBool& isMenuBar) = 0;
NS_IMETHOD DismissChain() = 0;
NS_IMETHOD HideChain() = 0;
NS_IMETHOD CreateDismissalListener() = 0;
};
#endif

View File

@@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsIScrollbarListener_h___
#define nsIScrollbarListener_h___
// {A0ADBD81-2911-11d3-97FA-00400553EEF0}
#define NS_ISCROLLBARLISTENER_IID \
{ 0xa0adbd81, 0x2911, 0x11d3, { 0x97, 0xfa, 0x0, 0x40, 0x5, 0x53, 0xee, 0xf0 } }
static NS_DEFINE_IID(kIScrollbarListenerIID, NS_ISCROLLBARLISTENER_IID);
class nsIPresContext;
class nsIScrollbarListener : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_ISCROLLBARLISTENER_IID; return iid; }
NS_IMETHOD PositionChanged(nsIPresContext& aPresContext, PRInt32 aOldIndex, PRInt32 aNewIndex) = 0;
NS_IMETHOD PagedUpDown() = 0;
// NS_IMETHOD GoingAway() = 0;
};
#endif

View File

@@ -0,0 +1,537 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
#include "nsMenuBarFrame.h"
#include "nsIContent.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsCSSRendering.h"
#include "nsINameSpaceManager.h"
#include "nsIDocument.h"
#include "nsIDOMEventReceiver.h"
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsMenuFrame.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsMenuPopupFrame.h"
static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID);
//
// NS_NewMenuBarFrame
//
// Wrapper for creating a new menu Bar container
//
nsresult
NS_NewMenuBarFrame(nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMenuBarFrame* it = new nsMenuBarFrame;
if ( !it )
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
nsMenuBarFrame::AddRef(void)
{
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
nsMenuBarFrame::Release(void)
{
return NS_OK;
}
NS_IMETHODIMP nsMenuBarFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(nsIMenuParent::GetIID())) {
*aInstancePtr = (void*)(nsIMenuParent*) this;
NS_ADDREF_THIS();
return NS_OK;
}
return nsToolbarFrame::QueryInterface(aIID, aInstancePtr);
}
//
// nsMenuBarFrame cntr
//
nsMenuBarFrame::nsMenuBarFrame()
:mIsActive(PR_FALSE), mTarget(nsnull)
{
} // cntr
nsMenuBarFrame::~nsMenuBarFrame()
{
}
NS_IMETHODIMP
nsMenuBarFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsToolbarFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
// XXX hack
mPresContext = &aPresContext;
// Create the menu bar listener.
mMenuBarListener = new nsMenuBarListener(this);
// Hook up the menu bar as a key listener (capturer) on the whole document. It will see every
// key press that occurs before anyone else does and will know when to take control.
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMEventReceiver> target = do_QueryInterface(doc);
nsIDOMEventListener* domEventListener = (nsIDOMKeyListener*)mMenuBarListener;
mTarget = target;
target->AddEventListener("keypress", domEventListener, PR_TRUE);
target->AddEventListener("keydown", domEventListener, PR_TRUE);
target->AddEventListener("keyup", domEventListener, PR_TRUE);
return rv;
}
NS_IMETHODIMP
nsMenuBarFrame::SetActive(PRBool aActiveFlag)
{
mIsActive = aActiveFlag;
return NS_OK;
}
void
nsMenuBarFrame::ToggleMenuActiveState()
{
if (mIsActive) {
// Deactivate the menu bar
mIsActive = PR_FALSE;
if (mCurrentMenu) {
// Deactivate the menu.
mCurrentMenu->OpenMenu(PR_FALSE);
mCurrentMenu->SelectMenu(PR_FALSE);
mCurrentMenu = nsnull;
}
}
else {
// Activate the menu bar
SetActive(PR_TRUE);
// Set the active menu to be the top left item (e.g., the File menu).
// We use an attribute called "active" to track the current active menu.
nsCOMPtr<nsIContent> firstMenuItem;
nsIMenuFrame* firstFrame;
GetNextMenuItem(nsnull, &firstFrame);
if (firstFrame) {
firstFrame->SelectMenu(PR_TRUE);
// Track this item for keyboard navigation.
mCurrentMenu = firstFrame;
}
}
}
nsIMenuFrame*
nsMenuBarFrame::FindMenuWithShortcut(PRUint32 aLetter)
{
// Enumerate over our list of frames.
nsIFrame* currFrame = mFrames.FirstChild();
while (currFrame) {
nsCOMPtr<nsIContent> current;
currFrame->GetContent(getter_AddRefs(current));
// See if it's a menu item.
if (IsValidItem(current)) {
// Get the shortcut attribute.
nsString shortcutKey = "";
current->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, shortcutKey);
shortcutKey.ToUpperCase();
if (shortcutKey.Length() > 0) {
// We've got something.
PRUnichar shortcutChar = shortcutKey.CharAt(0);
if (shortcutChar == aLetter) {
// We match!
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
if (menuFrame)
return menuFrame.get();
return nsnull;
}
}
}
currFrame->GetNextSibling(&currFrame);
}
return nsnull;
}
void
nsMenuBarFrame::ShortcutNavigation(PRUint32 aLetter, PRBool& aHandledFlag)
{
if (mCurrentMenu) {
PRBool isOpen = PR_FALSE;
mCurrentMenu->MenuIsOpen(isOpen);
if (isOpen) {
// No way this applies to us. Give it to our child.
mCurrentMenu->ShortcutNavigation(aLetter, aHandledFlag);
return;
}
}
// This applies to us. Let's see if one of the shortcuts applies
nsIMenuFrame* result = FindMenuWithShortcut(aLetter);
if (result) {
// We got one!
aHandledFlag = PR_TRUE;
mIsActive = PR_TRUE;
SetCurrentMenuItem(result);
result->OpenMenu(PR_TRUE);
result->SelectFirstItem();
}
}
void
nsMenuBarFrame::KeyboardNavigation(PRUint32 aDirection)
{
if (!mCurrentMenu)
return;
PRBool isContainer = PR_FALSE;
PRBool isOpen = PR_FALSE;
mCurrentMenu->MenuIsContainer(isContainer);
mCurrentMenu->MenuIsOpen(isOpen);
PRBool handled = PR_FALSE;
if (isOpen) {
// Let the child menu try to handle it.
mCurrentMenu->KeyboardNavigation(aDirection, handled);
}
if (handled)
return;
if (aDirection == NS_VK_RIGHT || aDirection == NS_VK_LEFT) {
nsIMenuFrame* nextItem;
if (aDirection == NS_VK_RIGHT)
GetNextMenuItem(mCurrentMenu, &nextItem);
else GetPreviousMenuItem(mCurrentMenu, &nextItem);
SetCurrentMenuItem(nextItem);
if (nextItem) {
PRBool nextIsOpen;
nextItem->MenuIsOpen(nextIsOpen);
if (nextIsOpen) {
// Select the first item.
nextItem->SelectFirstItem();
}
}
}
else if (aDirection == NS_VK_UP || aDirection == NS_VK_DOWN) {
// Open the menu and select its first item.
mCurrentMenu->OpenMenu(PR_TRUE);
mCurrentMenu->SelectFirstItem();
}
}
NS_IMETHODIMP
nsMenuBarFrame::GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
{
nsIFrame* currFrame = nsnull;
nsIFrame* startFrame = nsnull;
if (aStart) {
aStart->QueryInterface(kIFrameIID, (void**)&currFrame);
if (currFrame) {
startFrame = currFrame;
currFrame->GetNextSibling(&currFrame);
}
}
else currFrame = mFrames.FirstChild();
while (currFrame) {
nsCOMPtr<nsIContent> current;
currFrame->GetContent(getter_AddRefs(current));
// See if it's a menu item.
if (IsValidItem(current)) {
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
*aResult = menuFrame.get();
NS_IF_ADDREF(*aResult);
return NS_OK;
}
currFrame->GetNextSibling(&currFrame);
}
currFrame = mFrames.FirstChild();
// Still don't have anything. Try cycling from the beginning.
while (currFrame && currFrame != startFrame) {
nsCOMPtr<nsIContent> current;
currFrame->GetContent(getter_AddRefs(current));
// See if it's a menu item.
if (IsValidItem(current)) {
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
*aResult = menuFrame.get();
NS_IF_ADDREF(*aResult);
return NS_OK;
}
currFrame->GetNextSibling(&currFrame);
}
// No luck. Just return our start value.
*aResult = aStart;
return NS_OK;
}
NS_IMETHODIMP
nsMenuBarFrame::GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
{
nsIFrame* currFrame = nsnull;
nsIFrame* startFrame = nsnull;
if (aStart) {
aStart->QueryInterface(kIFrameIID, (void**)&currFrame);
if (currFrame) {
startFrame = currFrame;
currFrame = mFrames.GetPrevSiblingFor(currFrame);
}
}
else currFrame = mFrames.LastChild();
while (currFrame) {
nsCOMPtr<nsIContent> current;
currFrame->GetContent(getter_AddRefs(current));
// See if it's a menu item.
if (IsValidItem(current)) {
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
*aResult = menuFrame.get();
NS_IF_ADDREF(*aResult);
return NS_OK;
}
currFrame = mFrames.GetPrevSiblingFor(currFrame);
}
currFrame = mFrames.LastChild();
// Still don't have anything. Try cycling from the end.
while (currFrame && currFrame != startFrame) {
nsCOMPtr<nsIContent> current;
currFrame->GetContent(getter_AddRefs(current));
// See if it's a menu item.
if (IsValidItem(current)) {
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
*aResult = menuFrame.get();
NS_IF_ADDREF(*aResult);
return NS_OK;
}
currFrame = mFrames.GetPrevSiblingFor(currFrame);
}
// No luck. Just return our start value.
*aResult = aStart;
return NS_OK;
}
NS_IMETHODIMP nsMenuBarFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
{
if (mCurrentMenu == aMenuItem)
return NS_OK;
PRBool wasOpen = PR_FALSE;
// Unset the current child.
if (mCurrentMenu) {
mCurrentMenu->MenuIsOpen(wasOpen);
mCurrentMenu->SelectMenu(PR_FALSE);
if (wasOpen)
mCurrentMenu->OpenMenu(PR_FALSE);
}
// Set the new child.
if (aMenuItem) {
aMenuItem->SelectMenu(PR_TRUE);
aMenuItem->MarkAsGenerated(); // Have the menu building. Get it ready to be shown.
if (wasOpen)
aMenuItem->OpenMenu(PR_TRUE);
}
mCurrentMenu = aMenuItem;
return NS_OK;
}
void
nsMenuBarFrame::Escape()
{
if (!mCurrentMenu)
return;
// See if our menu is open.
PRBool isOpen = PR_FALSE;
mCurrentMenu->MenuIsOpen(isOpen);
if (isOpen) {
// Let the child menu handle this.
PRBool handled = PR_FALSE;
mCurrentMenu->Escape(handled);
if (!handled) {
// Close up this menu but keep our current menu item
// designation.
mCurrentMenu->OpenMenu(PR_FALSE);
}
return;
}
// It's us. Just set our active flag to false.
mIsActive = PR_FALSE;
// Clear our current menu item if we've got one.
SetCurrentMenuItem(nsnull);
// Clear out our dismissal listener
if (nsMenuFrame::mDismissalListener)
nsMenuFrame::mDismissalListener->Unregister();
}
void
nsMenuBarFrame::Enter()
{
if (!mCurrentMenu)
return;
// See if our menu is open.
PRBool isOpen = PR_FALSE;
mCurrentMenu->MenuIsOpen(isOpen);
if (isOpen) {
// Let the child menu handle this.
mCurrentMenu->Enter();
return;
}
// It's us. Open the current menu.
mCurrentMenu->OpenMenu(PR_TRUE);
mCurrentMenu->SelectFirstItem();
}
NS_IMETHODIMP
nsMenuBarFrame::HideChain()
{
// Stop capturing rollups
// (must do this during Hide, which happens before the menu item is executed,
// since this reinstates normal event handling.)
if (nsMenuFrame::mDismissalListener)
nsMenuFrame::mDismissalListener->Unregister();
if (mCurrentMenu) {
mCurrentMenu->ActivateMenu(PR_FALSE);
mCurrentMenu->SelectMenu(PR_FALSE);
}
return NS_OK;
}
NS_IMETHODIMP
nsMenuBarFrame::DismissChain()
{
// Stop capturing rollups
if (nsMenuFrame::mDismissalListener)
nsMenuFrame::mDismissalListener->Unregister();
SetCurrentMenuItem(nsnull);
SetActive(PR_FALSE);
return NS_OK;
}
NS_IMETHODIMP
nsMenuBarFrame::GetWidget(nsIWidget **aWidget)
{
// Get parent view
nsIView * view = nsnull;
nsMenuPopupFrame::GetNearestEnclosingView(mPresContext, this, &view);
if (!view)
return NS_OK;
view->GetWidget(*aWidget);
return NS_OK;
}
NS_IMETHODIMP
nsMenuBarFrame::CreateDismissalListener()
{
NS_ADDREF(nsMenuFrame::mDismissalListener = new nsMenuDismissalListener());
return NS_OK;
}
PRBool
nsMenuBarFrame::IsValidItem(nsIContent* aContent)
{
nsCOMPtr<nsIAtom> tag;
aContent->GetTag(*getter_AddRefs(tag));
if (tag && (tag.get() == nsXULAtoms::menu ||
tag.get() == nsXULAtoms::menuitem) &&
!IsDisabled(aContent))
return PR_TRUE;
return PR_FALSE;
}
PRBool
nsMenuBarFrame::IsDisabled(nsIContent* aContent)
{
nsString disabled = "";
aContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::disabled, disabled);
if (disabled == "true")
return PR_TRUE;
return PR_FALSE;
}
NS_IMETHODIMP
nsMenuBarFrame::Destroy(nsIPresContext& aPresContext)
{
mTarget->RemoveEventListener("keypress", mMenuBarListener, PR_TRUE);
mTarget->RemoveEventListener("keydown", mMenuBarListener, PR_TRUE);
mTarget->RemoveEventListener("keyup", mMenuBarListener, PR_TRUE);
delete mMenuBarListener;
mMenuBarListener = nsnull;
return nsToolbarFrame::Destroy(aPresContext);
}

View File

@@ -0,0 +1,108 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
//
// nsMenuBarFrame
//
#ifndef nsMenuBarFrame_h__
#define nsMenuBarFrame_h__
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsCOMPtr.h"
#include "nsToolbarFrame.h"
#include "nsMenuBarListener.h"
#include "nsIMenuParent.h"
#include "nsIWidget.h"
class nsIContent;
class nsIMenuFrame;
nsresult NS_NewMenuBarFrame(nsIFrame** aResult) ;
class nsMenuBarFrame : public nsToolbarFrame, public nsIMenuParent
{
public:
nsMenuBarFrame();
~nsMenuBarFrame();
NS_DECL_ISUPPORTS
// nsIMenuParentInterface
NS_IMETHOD SetCurrentMenuItem(nsIMenuFrame* aMenuItem);
NS_IMETHOD GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult);
NS_IMETHOD GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult);
NS_IMETHOD SetActive(PRBool aActiveFlag);
NS_IMETHOD GetIsActive(PRBool& isActive) { isActive = IsActive(); return NS_OK; };
NS_IMETHOD IsMenuBar(PRBool& isMenuBar) { isMenuBar = PR_TRUE; return NS_OK; };
NS_IMETHOD IsActive() { return mIsActive; };
// Closes up the chain of open cascaded menus.
NS_IMETHOD DismissChain();
// Hides the chain of cascaded menus without closing them up.
NS_IMETHOD HideChain();
NS_IMETHOD GetWidget(nsIWidget **aWidget);
// The dismissal listener gets created and attached to the window.
NS_IMETHOD CreateDismissalListener();
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
// Non-interface helpers
// Called when a menu on the menu bar is clicked on.
void ToggleMenuActiveState();
// Used to move up, down, left, and right in menus.
void KeyboardNavigation(PRUint32 aDirection);
// Used to handle ALT+key combos
void ShortcutNavigation(PRUint32 aLetter, PRBool& aHandledFlag);
nsIMenuFrame* FindMenuWithShortcut(PRUint32 aLetter);
// Called when the ESC key is held down to close levels of menus.
void Escape();
// Called to execute a menu item.
void Enter();
PRBool IsValidItem(nsIContent* aContent);
PRBool IsDisabled(nsIContent* aContent);
protected:
nsMenuBarListener* mMenuBarListener; // The listener that tells us about key and mouse events.
PRBool mIsActive; // Whether or not the menu bar is active (a menu item is highlighted or shown).
nsIMenuFrame* mCurrentMenu; // The current menu that is active.
nsIDOMEventReceiver* mTarget;
// XXX Hack
nsIPresContext* mPresContext; // weak reference
}; // class nsMenuBarFrame
#endif

View File

@@ -0,0 +1,190 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsMenuBarListener.h"
#include "nsMenuBarFrame.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMEventListener.h"
// Drag & Drop, Clipboard
#include "nsIServiceManager.h"
#include "nsWidgetsCID.h"
#include "nsCOMPtr.h"
#include "nsIDOMKeyEvent.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
#include "nsIDOMNode.h"
#include "nsIDOMElement.h"
#include "nsXULAtoms.h"
#include "nsIEventStateManager.h"
#include "nsIViewManager.h"
#include "nsIView.h"
#include "nsISupportsArray.h"
/*
* nsMenuBarListener implementation
*/
NS_IMPL_ADDREF(nsMenuBarListener)
NS_IMPL_RELEASE(nsMenuBarListener)
////////////////////////////////////////////////////////////////////////
nsMenuBarListener::nsMenuBarListener(nsMenuBarFrame* aMenuBar)
:mAltKeyDown(PR_FALSE)
{
NS_INIT_REFCNT();
mMenuBarFrame = aMenuBar;
}
////////////////////////////////////////////////////////////////////////
nsMenuBarListener::~nsMenuBarListener()
{
}
////////////////////////////////////////////////////////////////////////
nsresult
nsMenuBarListener::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(nsCOMTypeInfo<nsIDOMEventReceiver>::GetIID())) {
*aInstancePtr = (void*)(nsIDOMEventListener*)(nsIDOMKeyListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsCOMTypeInfo<nsIDOMKeyListener>::GetIID())) {
*aInstancePtr = (void*)(nsIDOMKeyListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID())) {
*aInstancePtr = (void*)(nsISupports*)(nsIDOMKeyListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
////////////////////////////////////////////////////////////////////////
nsresult
nsMenuBarListener::KeyUp(nsIDOMEvent* aKeyEvent)
{
// On a press of the ALT key by itself, we toggle the menu's
// active/inactive state.
// Get the ascii key code.
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
PRUint32 theChar;
keyEvent->GetKeyCode(&theChar);
if (theChar == NS_VK_ALT && mAltKeyDown) {
// The ALT key was down and is now up.
mAltKeyDown = PR_FALSE;
mMenuBarFrame->ToggleMenuActiveState();
}
PRBool active = mMenuBarFrame->IsActive();
if (active)
return NS_ERROR_BASE; // I am consuming event
return NS_OK; // means I am NOT consuming event
}
////////////////////////////////////////////////////////////////////////
nsresult
nsMenuBarListener::KeyDown(nsIDOMEvent* aKeyEvent)
{
PRBool active = mMenuBarFrame->IsActive();
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
PRUint32 theChar;
keyEvent->GetKeyCode(&theChar);
if (theChar == NS_VK_ALT) {
// The ALT key just went down. Track this.
mAltKeyDown = PR_TRUE;
return NS_OK;
}
PRBool altKeyWasDown = mAltKeyDown;
mAltKeyDown = PR_FALSE;
if (theChar == NS_VK_LEFT ||
theChar == NS_VK_RIGHT ||
theChar == NS_VK_UP ||
theChar == NS_VK_DOWN) {
// The arrow keys were pressed. User is moving around within
// the menus.
if (active)
mMenuBarFrame->KeyboardNavigation(theChar);
}
else if (theChar == NS_VK_ESCAPE) {
// Close one level.
if (active)
mMenuBarFrame->Escape();
}
else if (theChar == NS_VK_ENTER ||
theChar == NS_VK_RETURN) {
// Open one level.
if (active)
mMenuBarFrame->Enter();
}
else if (active || altKeyWasDown) {
// Get the character code.
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
if (keyEvent) {
// See if a letter was pressed.
PRUint32 charCode;
keyEvent->GetKeyCode(&charCode);
// Do shortcut navigation.
// A letter was pressed. We want to see if a shortcut gets matched. If
// so, we'll know the menu got activated.
mMenuBarFrame->ShortcutNavigation(charCode, active);
}
}
if (active)
return NS_ERROR_BASE; // I am consuming event
return NS_OK; // means I am NOT consuming event
}
////////////////////////////////////////////////////////////////////////
nsresult
nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent)
{
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
PRBool active = mMenuBarFrame->IsActive();
if (active)
return NS_ERROR_BASE; // I am consuming event
return NS_OK; // means I am NOT consuming event
}
////////////////////////////////////////////////////////////////////////
nsresult
nsMenuBarListener::HandleEvent(nsIDOMEvent* aEvent)
{
return NS_OK;
}

View File

@@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsMenuBarListener_h__
#define nsMenuBarListener_h__
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMEventReceiver.h"
class nsMenuBarFrame;
class nsIPresContext;
/** editor Implementation of the DragListener interface
*/
class nsMenuBarListener : public nsIDOMKeyListener
{
public:
/** default constructor
*/
nsMenuBarListener(nsMenuBarFrame* aMenuBar);
/** default destructor
*/
virtual ~nsMenuBarListener();
virtual nsresult HandleEvent(nsIDOMEvent* aEvent);
virtual nsresult KeyUp(nsIDOMEvent* aMouseEvent);
virtual nsresult KeyDown(nsIDOMEvent* aMouseEvent);
virtual nsresult KeyPress(nsIDOMEvent* aMouseEvent);
NS_DECL_ISUPPORTS
protected:
nsMenuBarFrame* mMenuBarFrame; // The menu bar object.
PRBool mAltKeyDown; // Whether or not the ALT key is currently down.
};
#endif

View File

@@ -0,0 +1,140 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsMenuDismissalListener.h"
#include "nsIMenuParent.h"
#include "nsMenuFrame.h"
/*
* nsMenuDismissalListener implementation
*/
NS_IMPL_ADDREF(nsMenuDismissalListener)
NS_IMPL_RELEASE(nsMenuDismissalListener)
////////////////////////////////////////////////////////////////////////
nsMenuDismissalListener::nsMenuDismissalListener() :
mWidget(0), mEnabled(PR_TRUE)
{
NS_INIT_REFCNT();
mMenuParent = nsnull;
}
////////////////////////////////////////////////////////////////////////
nsMenuDismissalListener::~nsMenuDismissalListener()
{
}
////////////////////////////////////////////////////////////////////////
nsresult
nsMenuDismissalListener::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(nsCOMTypeInfo<nsIDOMEventReceiver>::GetIID())) {
*aInstancePtr = (void*)(nsIDOMEventListener*)(nsIDOMKeyListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsCOMTypeInfo<nsIDOMMouseListener>::GetIID())) {
*aInstancePtr = (void*)(nsIDOMMouseListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsCOMTypeInfo<nsIRollupListener>::GetIID())) {
*aInstancePtr = (void*)(nsIRollupListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID())) {
*aInstancePtr = (void*)(nsISupports*)(nsIDOMMouseListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
////////////////////////////////////////////////////////////////////////
nsresult
nsMenuDismissalListener::MouseDown(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
void
nsMenuDismissalListener::SetCurrentMenuParent(nsIMenuParent* aMenuParent)
{
if (aMenuParent == mMenuParent)
return;
nsCOMPtr<nsIRollupListener> kungFuDeathGrip = this;
Unregister();
mMenuParent = aMenuParent;
if (!aMenuParent)
return;
nsCOMPtr<nsIWidget> widget;
aMenuParent->GetWidget(getter_AddRefs(widget));
if (!widget)
return;
widget->CaptureRollupEvents(this, PR_TRUE, PR_FALSE);
mWidget = widget;
NS_ADDREF(nsMenuFrame::mDismissalListener = this);
}
NS_IMETHODIMP
nsMenuDismissalListener::Rollup()
{
if (mEnabled) {
if (mMenuParent) {
AddRef();
mMenuParent->HideChain();
mMenuParent->DismissChain();
Release();
}
else
Unregister();
}
return NS_OK;
}
NS_IMETHODIMP
nsMenuDismissalListener::Unregister()
{
if (mWidget)
mWidget->CaptureRollupEvents(this, PR_FALSE, PR_FALSE);
NS_RELEASE(nsMenuFrame::mDismissalListener);
return NS_OK;
}
NS_IMETHODIMP
nsMenuDismissalListener::EnableListener(PRBool aEnabled)
{
mEnabled = aEnabled;
return NS_OK;
}

View File

@@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsMenuDismissalListener_h__
#define nsMenuDismissalListener_h__
#include "nsIWidget.h"
#include "nsIDOMMouseListener.h"
#include "nsIRollupListener.h"
#include "nsIDOMEventReceiver.h"
class nsMenuPopupFrame;
class nsIPresContext;
class nsIMenuParent;
/** editor Implementation of the DragListener interface
*/
class nsMenuDismissalListener : public nsIDOMMouseListener, public nsIRollupListener
{
public:
/** default constructor
*/
nsMenuDismissalListener();
/** default destructor
*/
virtual ~nsMenuDismissalListener();
virtual nsresult HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; };
virtual nsresult MouseDown(nsIDOMEvent* aMouseEvent);
virtual nsresult MouseUp(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseClick(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; };
virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) { return NS_OK; };
NS_IMETHOD Rollup();
NS_DECL_ISUPPORTS
NS_IMETHOD EnableListener(PRBool aEnabled);
void SetCurrentMenuParent(nsIMenuParent* aMenuParent);
NS_IMETHOD Unregister();
protected:
nsIMenuParent* mMenuParent;
nsIWidget* mWidget;
PRBool mEnabled;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,199 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
//
// nsMenuFrame
//
#ifndef nsMenuFrame_h__
#define nsMenuFrame_h__
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsCOMPtr.h"
#include "nsIAnonymousContentCreator.h"
#include "nsBoxFrame.h"
#include "nsFrameList.h"
#include "nsIMenuParent.h"
#include "nsIMenuFrame.h"
#include "nsMenuDismissalListener.h"
#include "nsITimer.h"
#include "nsITimerCallback.h"
#include "nsISupportsArray.h"
#include "nsIDOMText.h"
#include "nsIContent.h"
nsresult NS_NewMenuFrame(nsIFrame** aResult, PRUint32 aFlags) ;
class nsMenuBarFrame;
class nsMenuPopupFrame;
class nsMenuFrame : public nsBoxFrame,
public nsIMenuFrame,
public nsITimerCallback,
public nsIAnonymousContentCreator
{
public:
nsMenuFrame();
NS_DECL_ISUPPORTS
// The nsIAnonymousContentCreator interface
NS_IMETHOD CreateAnonymousContent(nsISupportsArray& aAnonymousItems);
// The nsITimerCallback interface
virtual void Notify(nsITimer *timer);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD IsActive(PRBool& aResult) { aResult = PR_TRUE; return NS_OK; };
// The following four methods are all overridden so that the menu children
// can be stored in a separate list (so that they don't impact reflow of the
// actual menu item at all).
NS_IMETHOD FirstChild(nsIAtom* aListName,
nsIFrame** aFirstChild) const;
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex,
nsIAtom** aListName) const;
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
// Overridden to prevent events from ever going to children of the menu.
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
// Reflow methods
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus);
NS_IMETHOD Dirty(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild);
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame);
// nsIMenuFrame Interface
NS_IMETHOD ActivateMenu(PRBool aActivateFlag);
NS_IMETHOD SelectMenu(PRBool aActivateFlag);
NS_IMETHOD OpenMenu(PRBool aActivateFlag);
NS_IMETHOD MenuIsOpen(PRBool& aResult) { aResult = IsOpen(); return NS_OK; };
NS_IMETHOD MenuIsContainer(PRBool& aResult) { aResult = IsMenu(); return NS_OK; };
NS_IMETHOD MenuIsChecked(PRBool& aResult) { aResult = mChecked; return NS_OK; };
NS_IMETHOD SelectFirstItem();
NS_IMETHOD Escape(PRBool& aHandledFlag);
NS_IMETHOD Enter();
NS_IMETHOD ShortcutNavigation(PRUint32 aLetter, PRBool& aHandledFlag);
NS_IMETHOD KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag);
NS_IMETHOD GetMenuParent(nsIMenuParent** aResult) { NS_IF_ADDREF(mMenuParent); *aResult = mMenuParent; return NS_OK; };
NS_IMETHOD GetRadioGroupName(nsString &aName) { aName = mGroupName; return NS_OK; };
NS_IMETHOD GetMenuType(nsMenuType &aType) { aType = mType; return NS_OK; };
NS_IMETHOD MarkAsGenerated();
// nsMenuFrame methods
PRBool IsOpen() { return mMenuOpen; };
PRBool IsMenu();
PRBool IsDisabled();
PRBool IsGenerated();
NS_IMETHOD ToggleMenuState();
void SetIsMenu(PRBool aIsMenu) { mIsMenu = aIsMenu; };
protected:
static void UpdateDismissalListener(nsIMenuParent* aMenuParent);
void UpdateMenuType();
void UpdateMenuSpecialState();
void OpenMenuInternal(PRBool aActivateFlag);
void GetMenuChildrenElement(nsIContent** aResult);
// Called to split the accesskey attribute up based on the specified string.
void SplitOnShortcut(nsString& aBeforeString, nsString& aAccessString, nsString& aAfterString);
// Examines the key node and builds the accelerator.
void BuildAcceleratorText(nsString& aAccelString);
// Called to execute our command handler.
void Execute();
// Called as a hook just before the menu gets opened.
PRBool OnCreate();
// Called as a hook just before the menu goes away.
PRBool OnDestroy();
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint);
protected:
nsFrameList mPopupFrames;
PRPackedBool mIsMenu; // Whether or not we can even have children or not.
PRPackedBool mMenuOpen;
PRPackedBool mHasAnonymousContent; // Do we have anonymous content frames?
PRPackedBool mChecked; // if so, are we checked?
nsMenuType mType;
nsCOMPtr<nsIContent> mMenuText;
nsCOMPtr<nsIContent> mAccelText;
nsIMenuParent* mMenuParent; // Our parent menu.
nsCOMPtr<nsITimer> mOpenTimer;
nsIPresContext* mPresContext; // Our pres context.
nsString mGroupName;
public:
static nsMenuDismissalListener* mDismissalListener; // The listener that dismisses menus.
}; // class nsMenuFrame
#endif

View File

@@ -0,0 +1,757 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
#include "nsMenuPopupFrame.h"
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsIContent.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsCSSRendering.h"
#include "nsINameSpaceManager.h"
#include "nsIViewManager.h"
#include "nsWidgetsCID.h"
#include "nsMenuFrame.h"
#include "nsIPopupSetFrame.h"
const PRInt32 kMaxZ = 0x7fffffff; //XXX: Shouldn't there be a define somewhere for MaxInt for PRInt32
static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID);
// NS_NewMenuPopupFrame
//
// Wrapper for creating a new menu popup container
//
nsresult
NS_NewMenuPopupFrame(nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMenuPopupFrame* it = new nsMenuPopupFrame;
if ( !it )
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
nsMenuPopupFrame::AddRef(void)
{
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
nsMenuPopupFrame::Release(void)
{
return NS_OK;
}
NS_IMETHODIMP nsMenuPopupFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(nsIMenuParent::GetIID())) {
*aInstancePtr = (void*)(nsIMenuParent*) this;
NS_ADDREF_THIS();
return NS_OK;
}
return nsBoxFrame::QueryInterface(aIID, aInstancePtr);
}
//
// nsMenuPopupFrame cntr
//
nsMenuPopupFrame::nsMenuPopupFrame()
:mCurrentMenu(nsnull)
{
} // cntr
NS_IMETHODIMP
nsMenuPopupFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
// XXX Hack
mPresContext = &aPresContext;
// We default to being vertical.
nsString value;
mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, value);
mHorizontal = PR_FALSE;
if (value.EqualsIgnoreCase("vertical"))
mHorizontal = PR_FALSE;
else if (value.EqualsIgnoreCase("horizontal"))
mHorizontal = PR_TRUE;
CreateViewForFrame(aPresContext, this, aContext, PR_TRUE);
// Now that we've made a view, remove it and insert it at the correct
// position in the view hierarchy (as the root view). We do this so that we
// can draw the menus outside the confines of the window.
nsIView* ourView;
GetView(&aPresContext, &ourView);
nsIFrame* parent;
aParent->GetParentWithView(&aPresContext, &parent);
nsIView* parentView;
parent->GetView(&aPresContext, &parentView);
nsCOMPtr<nsIViewManager> viewManager;
parentView->GetViewManager(*getter_AddRefs(viewManager));
// Remove the view from its old position.
viewManager->RemoveChild(parentView, ourView);
// Reinsert ourselves as the root view with a maximum z-index.
nsIView* rootView;
viewManager->GetRootView(rootView);
viewManager->InsertChild(rootView, ourView, kMaxZ);
// XXX Hack. Change our transparency to be non-transparent
// until the bug related to update of transparency on show/hide
// is fixed.
viewManager->SetViewContentTransparency(ourView, PR_FALSE);
// Create a widget for ourselves.
nsWidgetInitData widgetData;
ourView->SetZIndex(kMaxZ);
widgetData.mWindowType = eWindowType_popup;
widgetData.mBorderStyle = eBorderStyle_default;
// XXX make sure we are hidden (shouldn't this be done automatically?)
ourView->SetVisibility(nsViewVisibility_kHide);
#ifdef XP_MAC
printf("XP Popups: This is a nag to indicate that an inconsistent hack is being done on the Mac for popups.\n");
static NS_DEFINE_IID(kCPopupCID, NS_POPUP_CID);
ourView->CreateWidget(kCPopupCID, &widgetData, nsnull);
#else
static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID);
ourView->CreateWidget(kCChildCID, &widgetData, nsnull);
#endif
return rv;
}
void
nsMenuPopupFrame::GetViewOffset(nsIViewManager* aManager, nsIView* aView,
nsPoint& aPoint)
{
aPoint.x = 0;
aPoint.y = 0;
nsIView *parent;
nsRect bounds;
parent = aView;
while (nsnull != parent) {
parent->GetBounds(bounds);
aPoint.x += bounds.x;
aPoint.y += bounds.y;
parent->GetParent(parent);
}
}
void
nsMenuPopupFrame::GetNearestEnclosingView(nsIPresContext* aPresContext, nsIFrame* aStartFrame, nsIView** aResult)
{
*aResult = nsnull;
aStartFrame->GetView(aPresContext, aResult);
if (!*aResult) {
nsIFrame* parent;
aStartFrame->GetParentWithView(aPresContext, &parent);
if (parent)
parent->GetView(aPresContext, aResult);
}
}
nsresult
nsMenuPopupFrame::SyncViewWithFrame(nsIPresContext& aPresContext,
PRBool aOnMenuBar,
nsIFrame* aFrame,
PRInt32 aXPos, PRInt32 aYPos)
{
nsPoint parentPos;
nsCOMPtr<nsIViewManager> viewManager;
//Get the nearest enclosing parent view to aFrame.
nsIView* parentView = nsnull;
GetNearestEnclosingView(&aPresContext, aFrame, &parentView);
if (!parentView)
return NS_OK;
parentView->GetViewManager(*getter_AddRefs(viewManager));
GetViewOffset(viewManager, parentView, parentPos);
nsIView* view = nsnull;
GetView(&aPresContext, &view);
nsIView* containingView = nsnull;
nsPoint offset;
aFrame->GetOffsetFromView(&aPresContext, offset, &containingView);
nsRect parentRect;
aFrame->GetRect(parentRect);
const nsStyleDisplay* disp;
GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) disp);
PRBool viewIsVisible = (NS_STYLE_VISIBILITY_VISIBLE == disp->mVisible);
nsViewVisibility oldVisibility;
view->GetVisibility(oldVisibility);
PRBool viewWasVisible = (oldVisibility == nsViewVisibility_kShow);
if (viewWasVisible && (! viewIsVisible)) {
view->SetVisibility(nsViewVisibility_kHide);
}
viewManager->ResizeView(view, mRect.width, mRect.height);
if (aXPos != -1 || aYPos != -1) {
// Convert the screen coords to twips
float p2t;
aPresContext.GetScaledPixelsToTwips(&p2t);
PRInt32 xpos = NSIntPixelsToTwips(aXPos, p2t);
PRInt32 ypos = NSIntPixelsToTwips(aYPos, p2t);
viewManager->MoveViewTo(view, xpos, ypos);
}
else if (aOnMenuBar)
viewManager->MoveViewTo(view, parentPos.x + offset.x, parentPos.y + parentRect.height + offset.y );
else viewManager->MoveViewTo(view, parentPos.x + parentRect.width + offset.x, parentPos.y + offset.y );
if ((! viewWasVisible) && viewIsVisible) {
view->SetVisibility(nsViewVisibility_kShow);
}
return NS_OK;
}
NS_IMETHODIMP
nsMenuPopupFrame::DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus)
{
// Copied from nsContainerFrame reflow WITHOUT the call
// nsFrame::DidReflow(). nsFrame::DidReflow() will move us to the
// wrong place.
nsresult result = NS_OK; /* = nsFrame::DidReflow(aPresContext, aStatus) */
if (NS_FRAME_REFLOW_FINISHED == aStatus) {
// Apply DidReflow to each and every list that this frame implements
nsIAtom* listName = nsnull;
PRInt32 listIndex = 0;
do {
nsIFrame* kid;
FirstChild(listName, &kid);
while (nsnull != kid) {
kid->DidReflow(aPresContext, aStatus);
kid->GetNextSibling(&kid);
}
NS_IF_RELEASE(listName);
GetAdditionalChildListName(listIndex++, &listName);
} while(nsnull != listName);
}
NS_FRAME_TRACE_OUT("nsContainerFrame::DidReflow");
return result;
}
NS_IMETHODIMP
nsMenuPopupFrame::GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
{
nsIFrame* currFrame = nsnull;
nsIFrame* startFrame = nsnull;
if (aStart) {
aStart->QueryInterface(kIFrameIID, (void**)&currFrame);
if (currFrame) {
startFrame = currFrame;
currFrame->GetNextSibling(&currFrame);
}
}
else currFrame = mFrames.FirstChild();
while (currFrame) {
nsCOMPtr<nsIContent> current;
currFrame->GetContent(getter_AddRefs(current));
// See if it's a menu item.
if (IsValidItem(current)) {
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
*aResult = menuFrame.get();
NS_IF_ADDREF(*aResult);
return NS_OK;
}
currFrame->GetNextSibling(&currFrame);
}
currFrame = mFrames.FirstChild();
// Still don't have anything. Try cycling from the beginning.
while (currFrame && currFrame != startFrame) {
nsCOMPtr<nsIContent> current;
currFrame->GetContent(getter_AddRefs(current));
// See if it's a menu item.
if (IsValidItem(current)) {
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
*aResult = menuFrame.get();
NS_IF_ADDREF(*aResult);
return NS_OK;
}
currFrame->GetNextSibling(&currFrame);
}
// No luck. Just return our start value.
*aResult = aStart;
return NS_OK;
}
NS_IMETHODIMP
nsMenuPopupFrame::GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult)
{
nsIFrame* currFrame = nsnull;
nsIFrame* startFrame = nsnull;
if (aStart) {
aStart->QueryInterface(kIFrameIID, (void**)&currFrame);
if (currFrame) {
startFrame = currFrame;
currFrame = mFrames.GetPrevSiblingFor(currFrame);
}
}
else currFrame = mFrames.LastChild();
while (currFrame) {
nsCOMPtr<nsIContent> current;
currFrame->GetContent(getter_AddRefs(current));
// See if it's a menu item.
if (IsValidItem(current)) {
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
*aResult = menuFrame.get();
NS_IF_ADDREF(*aResult);
return NS_OK;
}
currFrame = mFrames.GetPrevSiblingFor(currFrame);
}
currFrame = mFrames.LastChild();
// Still don't have anything. Try cycling from the end.
while (currFrame && currFrame != startFrame) {
nsCOMPtr<nsIContent> current;
currFrame->GetContent(getter_AddRefs(current));
// See if it's a menu item.
if (IsValidItem(current)) {
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
*aResult = menuFrame.get();
NS_IF_ADDREF(*aResult);
return NS_OK;
}
currFrame = mFrames.GetPrevSiblingFor(currFrame);
}
// No luck. Just return our start value.
*aResult = aStart;
return NS_OK;
}
NS_IMETHODIMP nsMenuPopupFrame::SetCurrentMenuItem(nsIMenuFrame* aMenuItem)
{
if (mCurrentMenu == aMenuItem)
return NS_OK;
// Unset the current child.
if (mCurrentMenu) {
PRBool isOpen = PR_FALSE;
mCurrentMenu->MenuIsOpen(isOpen);
mCurrentMenu->SelectMenu(PR_FALSE);
if (isOpen)
mCurrentMenu->OpenMenu(PR_FALSE);
}
// Set the new child.
if (aMenuItem) {
aMenuItem->SelectMenu(PR_TRUE);
}
mCurrentMenu = aMenuItem;
return NS_OK;
}
NS_IMETHODIMP
nsMenuPopupFrame::CaptureMouseEvents(nsIPresContext* aPresContext, PRBool aGrabMouseEvents)
{
// get its view
nsIView* view = nsnull;
GetView(aPresContext, &view);
nsCOMPtr<nsIViewManager> viewMan;
PRBool result;
nsCOMPtr<nsIWidget> widget;
if (view) {
view->GetViewManager(*getter_AddRefs(viewMan));
if (viewMan) {
view->GetWidget(*getter_AddRefs(widget));
if (aGrabMouseEvents) {
viewMan->GrabMouseEvents(view,result);
mIsCapturingMouseEvents = PR_TRUE;
//widget->CaptureMouse(PR_TRUE);
} else {
viewMan->GrabMouseEvents(nsnull,result);
mIsCapturingMouseEvents = PR_FALSE;
//widget->CaptureMouse(PR_FALSE);
}
}
}
return NS_OK;
}
void
nsMenuPopupFrame::Escape(PRBool& aHandledFlag)
{
if (!mCurrentMenu)
return;
// See if our menu is open.
PRBool isOpen = PR_FALSE;
mCurrentMenu->MenuIsOpen(isOpen);
if (isOpen) {
// Let the child menu handle this.
mCurrentMenu->Escape(aHandledFlag);
if (!aHandledFlag) {
// We should close up.
mCurrentMenu->OpenMenu(PR_FALSE);
aHandledFlag = PR_TRUE;
}
return;
}
}
void
nsMenuPopupFrame::Enter()
{
// Give it to the child.
if (mCurrentMenu)
mCurrentMenu->Enter();
}
nsIMenuFrame*
nsMenuPopupFrame::FindMenuWithShortcut(PRUint32 aLetter)
{
// Enumerate over our list of frames.
nsIFrame* currFrame = mFrames.FirstChild();
while (currFrame) {
nsCOMPtr<nsIContent> current;
currFrame->GetContent(getter_AddRefs(current));
// See if it's a menu item.
if (IsValidItem(current)) {
// Get the shortcut attribute.
nsString shortcutKey = "";
current->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, shortcutKey);
shortcutKey.ToUpperCase();
if (shortcutKey.Length() > 0) {
// We've got something.
PRUnichar shortcutChar = shortcutKey.CharAt(0);
if (shortcutChar == aLetter) {
// We match!
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(currFrame);
if (menuFrame)
return menuFrame.get();
return nsnull;
}
}
}
currFrame->GetNextSibling(&currFrame);
}
return nsnull;
}
void
nsMenuPopupFrame::ShortcutNavigation(PRUint32 aLetter, PRBool& aHandledFlag)
{
if (mCurrentMenu) {
PRBool isOpen = PR_FALSE;
mCurrentMenu->MenuIsOpen(isOpen);
if (isOpen) {
// No way this applies to us. Give it to our child.
mCurrentMenu->ShortcutNavigation(aLetter, aHandledFlag);
return;
}
}
// This applies to us. Let's see if one of the shortcuts applies
nsIMenuFrame* result = FindMenuWithShortcut(aLetter);
if (result) {
// We got one!
aHandledFlag = PR_TRUE;
SetCurrentMenuItem(result);
result->OpenMenu(PR_TRUE);
result->SelectFirstItem();
// XXX For menu items, do an execution of the oncommand handler!
// Still needed or did I do this already? I'm going senile. - Dave
}
}
void
nsMenuPopupFrame::KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag)
{
// This method only gets called if we're open.
if (!mCurrentMenu && (aDirection == NS_VK_RIGHT || aDirection == NS_VK_LEFT)) {
// We've been opened, but we haven't had anything selected.
// We can handle RIGHT, but our parent handles LEFT.
if (aDirection == NS_VK_RIGHT) {
nsIMenuFrame* nextItem;
GetNextMenuItem(nsnull, &nextItem);
if (nextItem) {
aHandledFlag = PR_TRUE;
SetCurrentMenuItem(nextItem);
}
}
return;
}
PRBool isContainer = PR_FALSE;
PRBool isOpen = PR_FALSE;
if (mCurrentMenu) {
mCurrentMenu->MenuIsContainer(isContainer);
mCurrentMenu->MenuIsOpen(isOpen);
if (isOpen) {
// Give our child a shot.
mCurrentMenu->KeyboardNavigation(aDirection, aHandledFlag);
}
else if (aDirection == NS_VK_RIGHT && isContainer) {
// The menu is not yet open. Open it and select the first item.
aHandledFlag = PR_TRUE;
mCurrentMenu->OpenMenu(PR_TRUE);
mCurrentMenu->SelectFirstItem();
}
}
if (aHandledFlag)
return; // The child menu took it for us.
// For the vertical direction, we can move up or down.
if (aDirection == NS_VK_UP || aDirection == NS_VK_DOWN) {
nsIMenuFrame* nextItem;
if (aDirection == NS_VK_DOWN)
GetNextMenuItem(mCurrentMenu, &nextItem);
else GetPreviousMenuItem(mCurrentMenu, &nextItem);
SetCurrentMenuItem(nextItem);
aHandledFlag = PR_TRUE;
}
else if (mCurrentMenu && isContainer && isOpen) {
if (aDirection == NS_VK_LEFT) {
// Close it up.
mCurrentMenu->OpenMenu(PR_FALSE);
aHandledFlag = PR_TRUE;
}
}
}
NS_IMETHODIMP
nsMenuPopupFrame::GetParentPopup(nsIMenuParent** aMenuParent)
{
*aMenuParent = nsnull;
nsIFrame* frame;
GetParent(&frame);
if (frame) {
nsIFrame* grandparent;
frame->GetParent(&grandparent);
if (grandparent) {
nsCOMPtr<nsIMenuParent> menuParent = do_QueryInterface(grandparent);
if (menuParent) {
*aMenuParent = menuParent.get();
NS_ADDREF(*aMenuParent);
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsMenuPopupFrame::HideChain()
{
// Stop capturing rollups
// (must do this during Hide, which happens before the menu item is executed,
// since this reinstates normal event handling.)
if (nsMenuFrame::mDismissalListener)
nsMenuFrame::mDismissalListener->Unregister();
nsIFrame* frame;
GetParent(&frame);
if (frame) {
nsCOMPtr<nsIPopupSetFrame> popupSetFrame = do_QueryInterface(frame);
if (popupSetFrame) {
// Destroy the popup.
popupSetFrame->HidePopup();
return NS_OK;
}
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(frame);
if (!menuFrame)
return NS_OK;
menuFrame->ActivateMenu(PR_FALSE);
menuFrame->SelectMenu(PR_FALSE);
// Get the parent.
nsCOMPtr<nsIMenuParent> menuParent;
menuFrame->GetMenuParent(getter_AddRefs(menuParent));
if (menuParent)
menuParent->HideChain();
}
return NS_OK;
}
NS_IMETHODIMP
nsMenuPopupFrame::DismissChain()
{
// Stop capturing rollups
if (nsMenuFrame::mDismissalListener)
nsMenuFrame::mDismissalListener->Unregister();
// Get our menu parent.
nsIFrame* frame;
GetParent(&frame);
if (frame) {
nsCOMPtr<nsIPopupSetFrame> popupSetFrame = do_QueryInterface(frame);
if (popupSetFrame) {
// Destroy the popup.
popupSetFrame->DestroyPopup();
return NS_OK;
}
nsCOMPtr<nsIMenuFrame> menuFrame = do_QueryInterface(frame);
if (!menuFrame)
return NS_OK;
menuFrame->OpenMenu(PR_FALSE);
// Get the parent.
nsCOMPtr<nsIMenuParent> menuParent;
menuFrame->GetMenuParent(getter_AddRefs(menuParent));
if (menuParent)
menuParent->DismissChain();
}
return NS_OK;
}
NS_IMETHODIMP
nsMenuPopupFrame::GetWidget(nsIWidget **aWidget)
{
// Get parent view
nsIView * view = nsnull;
nsMenuPopupFrame::GetNearestEnclosingView(mPresContext, this, &view);
if (!view)
return NS_OK;
view->GetWidget(*aWidget);
return NS_OK;
}
NS_IMETHODIMP
nsMenuPopupFrame::CreateDismissalListener()
{
nsMenuDismissalListener *listener = new nsMenuDismissalListener();
if (!listener) return NS_ERROR_OUT_OF_MEMORY;
nsMenuFrame::mDismissalListener = listener;
NS_ADDREF(listener);
return NS_OK;
}
PRBool
nsMenuPopupFrame::IsValidItem(nsIContent* aContent)
{
nsCOMPtr<nsIAtom> tag;
aContent->GetTag(*getter_AddRefs(tag));
if (tag && (tag.get() == nsXULAtoms::menu ||
tag.get() == nsXULAtoms::menuitem) &&
!IsDisabled(aContent))
return PR_TRUE;
return PR_FALSE;
}
PRBool
nsMenuPopupFrame::IsDisabled(nsIContent* aContent)
{
nsString disabled = "";
aContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::disabled, disabled);
if (disabled == "true")
return PR_TRUE;
return PR_FALSE;
}
NS_IMETHODIMP
nsMenuPopupFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
NS_IMETHODIMP
nsMenuPopupFrame::Destroy(nsIPresContext& aPresContext)
{
//nsCOMPtr<nsIDOMEventReceiver> target = do_QueryInterface(mContent);
//target->RemoveEventListener("mousemove", mMenuPopupEntryListener, PR_TRUE);
return nsBoxFrame::Destroy(aPresContext);
}
NS_IMETHODIMP
nsMenuPopupFrame::GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame)
{
nsRect rect;
GetRect(rect);
if (rect.Contains(aPoint)) {
return nsBoxFrame::GetFrameForPoint(aPresContext, aPoint, aFrame);
}
*aFrame = this;
return NS_OK;
}

View File

@@ -0,0 +1,113 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
//
// nsMenuPopupFrame
//
#ifndef nsMenuPopupFrame_h__
#define nsMenuPopupFrame_h__
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsCOMPtr.h"
#include "nsBoxFrame.h"
#include "nsIMenuParent.h"
#include "nsIWidget.h"
nsresult NS_NewMenuPopupFrame(nsIFrame** aResult) ;
class nsIViewManager;
class nsIView;
class nsIMenuParent;
class nsIMenuFrame;
class nsMenuPopupFrame : public nsBoxFrame, public nsIMenuParent
{
public:
nsMenuPopupFrame();
NS_DECL_ISUPPORTS
// nsIMenuParentInterface
NS_IMETHOD SetCurrentMenuItem(nsIMenuFrame* aMenuItem);
NS_IMETHOD GetNextMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult);
NS_IMETHOD GetPreviousMenuItem(nsIMenuFrame* aStart, nsIMenuFrame** aResult);
NS_IMETHOD SetActive(PRBool aActiveFlag) { return NS_OK; }; // We don't care.
NS_IMETHOD GetIsActive(PRBool& isActive) { isActive = PR_FALSE; return NS_OK; };
NS_IMETHOD IsMenuBar(PRBool& isMenuBar) { isMenuBar = PR_FALSE; return NS_OK; };
NS_IMETHOD GetParentPopup(nsIMenuParent** aResult);
// Closes up the chain of open cascaded menus.
NS_IMETHOD DismissChain();
// Hides the chain of cascaded menus without closing them up.
NS_IMETHOD HideChain();
NS_IMETHOD GetWidget(nsIWidget **aWidget);
// The dismissal listener gets created and attached to the window.
NS_IMETHOD CreateDismissalListener();
// Overridden methods
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, nsIFrame** aFrame);
void GetViewOffset(nsIViewManager* aManager, nsIView* aView, nsPoint& aPoint);
static void GetNearestEnclosingView(nsIPresContext* aPresContext, nsIFrame* aStartFrame, nsIView** aResult);
nsresult SyncViewWithFrame(nsIPresContext& aPresContext, PRBool aOnMenuBar,
nsIFrame* aFrame, PRInt32 aXPos, PRInt32 aYPos);
NS_IMETHOD CaptureMouseEvents(nsIPresContext* aPresContext, PRBool aGrabMouseEvents);
void KeyboardNavigation(PRUint32 aDirection, PRBool& aHandledFlag);
void ShortcutNavigation(PRUint32 aLetter, PRBool& aHandledFlag);
nsIMenuFrame* FindMenuWithShortcut(PRUint32 aLetter);
void Escape(PRBool& aHandledFlag);
void Enter();
PRBool IsValidItem(nsIContent* aContent);
PRBool IsDisabled(nsIContent* aContent);
protected:
nsIMenuFrame* mCurrentMenu; // The current menu that is active.
PRBool mIsCapturingMouseEvents; // Whether or not we're grabbing the mouse events.
// XXX Hack
nsIPresContext* mPresContext; // weak reference
}; // class nsMenuPopupFrame
#endif

View File

@@ -0,0 +1,547 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsPopupSetFrame.h"
#include "nsIMenuParent.h"
#include "nsMenuFrame.h"
#include "nsBoxFrame.h"
#include "nsIContent.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsIReflowCommand.h"
#include "nsCSSRendering.h"
#include "nsINameSpaceManager.h"
#include "nsLayoutAtoms.h"
#include "nsMenuPopupFrame.h"
#include "nsMenuBarFrame.h"
#include "nsIView.h"
#include "nsIWidget.h"
#include "nsIDocument.h"
#include "nsIDOMNSDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMXULDocument.h"
#include "nsIDOMElement.h"
#include "nsISupportsArray.h"
#include "nsIDOMText.h"
#define NS_MENU_POPUP_LIST_INDEX (NS_AREA_FRAME_ABSOLUTE_LIST_INDEX + 1)
//
// NS_NewPopupSetFrame
//
// Wrapper for creating a new menu popup container
//
nsresult
NS_NewPopupSetFrame(nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsPopupSetFrame* it = new nsPopupSetFrame;
if ( !it )
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
nsPopupSetFrame::AddRef(void)
{
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
nsPopupSetFrame::Release(void)
{
return NS_OK;
}
NS_IMETHODIMP nsPopupSetFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(nsIPopupSetFrame::GetIID())) {
*aInstancePtr = (void*)(nsIPopupSetFrame*) this;
NS_ADDREF_THIS();
return NS_OK;
}
return nsBoxFrame::QueryInterface(aIID, aInstancePtr);
}
//
// nsPopupSetFrame cntr
//
nsPopupSetFrame::nsPopupSetFrame()
:mPresContext(nsnull), mElementFrame(nsnull)
{
} // cntr
nsIFrame*
nsPopupSetFrame::GetActiveChild()
{
return mPopupFrames.FirstChild();
}
NS_IMETHODIMP
nsPopupSetFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
mPresContext = &aPresContext; // Don't addref it. Our lifetime is shorter.
nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
return rv;
}
// The following methods are all overridden to ensure that the menupopup frames
// are placed in the appropriate list.
NS_IMETHODIMP
nsPopupSetFrame::FirstChild(nsIAtom* aListName,
nsIFrame** aFirstChild) const
{
if (nsLayoutAtoms::popupList == aListName) {
*aFirstChild = mPopupFrames.FirstChild();
} else {
nsBoxFrame::FirstChild(aListName, aFirstChild);
}
return NS_OK;
}
NS_IMETHODIMP
nsPopupSetFrame::SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsresult rv = NS_OK;
if (nsLayoutAtoms::popupList == aListName) {
mPopupFrames.SetFrames(aChildList);
} else {
nsFrameList frames(aChildList);
// We may have menupopups in here. Get them out, and move them into
// the popup frame list.
nsIFrame* frame = frames.FirstChild();
while (frame) {
nsCOMPtr<nsIContent> content;
frame->GetContent(getter_AddRefs(content));
nsCOMPtr<nsIAtom> tag;
content->GetTag(*getter_AddRefs(tag));
if (tag.get() == nsXULAtoms::popup) {
// Remove this frame from the list and place it in the other list.
frames.RemoveFrame(frame);
mPopupFrames.AppendFrame(this, frame);
nsIFrame* first = frames.FirstChild();
rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName, first);
return rv;
}
frame->GetNextSibling(&frame);
}
// Didn't find it.
rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList);
}
return rv;
}
NS_IMETHODIMP
nsPopupSetFrame::GetAdditionalChildListName(PRInt32 aIndex,
nsIAtom** aListName) const
{
// Maintain a separate child list for the menu contents.
// This is necessary because we don't want the menu contents to be included in the layout
// of the menu's single item because it would take up space, when it is supposed to
// be floating above the display.
/*NS_PRECONDITION(nsnull != aListName, "null OUT parameter pointer");
*aListName = nsnull;
if (NS_MENU_POPUP_LIST_INDEX == aIndex) {
*aListName = nsLayoutAtoms::popupList;
NS_ADDREF(*aListName);
return NS_OK;
}*/
return nsBoxFrame::GetAdditionalChildListName(aIndex, aListName);
}
NS_IMETHODIMP
nsPopupSetFrame::Destroy(nsIPresContext& aPresContext)
{
// Cleanup frames in popup child list
mPopupFrames.DestroyFrames(aPresContext);
return nsBoxFrame::Destroy(aPresContext);
}
NS_IMETHODIMP
nsPopupSetFrame::Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
nsIFrame* frame = GetActiveChild();
if (!frame || (rv != NS_OK))
return rv;
// Constrain the child's width and height to aAvailableWidth and aAvailableHeight
nsSize availSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame,
availSize);
kidReflowState.mComputedWidth = NS_UNCONSTRAINEDSIZE;
kidReflowState.mComputedHeight = NS_UNCONSTRAINEDSIZE;
// Reflow child
nscoord w = aDesiredSize.width;
nscoord h = aDesiredSize.height;
rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, aStatus);
// Set the child's width and height to its desired size
nsRect rect;
frame->GetRect(rect);
rect.width = aDesiredSize.width;
rect.height = aDesiredSize.height;
frame->SetRect(&aPresContext, rect);
// Don't let it affect our size.
aDesiredSize.width = w;
aDesiredSize.height = h;
return rv;
}
NS_IMETHODIMP
nsPopupSetFrame::DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus)
{
// Sync up the view.
nsIFrame* activeChild = GetActiveChild();
if (activeChild) {
((nsMenuPopupFrame*)activeChild)->SyncViewWithFrame(aPresContext, PR_TRUE, mElementFrame, mXPos, mYPos);
}
return nsBoxFrame::DidReflow(aPresContext, aStatus);
}
// Overridden Box method.
NS_IMETHODIMP
nsPopupSetFrame::Dirty(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild)
{
incrementalChild = nsnull;
nsresult rv = NS_OK;
// Dirty any children that need it.
nsIFrame* frame;
aReflowState.reflowCommand->GetNext(frame, PR_FALSE);
if (frame == nsnull) {
incrementalChild = this;
return rv;
}
// Now call our original box frame method
rv = nsBoxFrame::Dirty(aPresContext, aReflowState, incrementalChild);
if (rv != NS_OK || incrementalChild)
return rv;
nsIFrame* popup = GetActiveChild();
if (popup && (frame == popup)) {
// An incremental reflow command is targeting something inside our
// hidden popup view. We can't actually return the child, since it
// won't ever be found by box. Instead return ourselves, so that box
// will later send us an incremental reflow command.
incrementalChild = this;
// In order for the child box to know what it needs to reflow, we need
// to call its Dirty method...
nsIFrame* ignore;
nsIBox* ibox;
if (NS_SUCCEEDED(popup->QueryInterface(nsIBox::GetIID(), (void**)&ibox)) && ibox)
ibox->Dirty(aPresContext, aReflowState, ignore);
}
return rv;
}
NS_IMETHODIMP
nsPopupSetFrame::RemoveFrame(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame)
{
// need to rebuild all the springs.
for (int i=0; i < mSpringCount; i++)
mSprings[i].clear();
nsresult rv;
if (mPopupFrames.ContainsFrame(aOldFrame)) {
// Go ahead and remove this frame.
mPopupFrames.DestroyFrame(aPresContext, aOldFrame);
rv = GenerateDirtyReflowCommand(aPresContext, aPresShell);
} else {
rv = nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame);
}
return rv;
}
NS_IMETHODIMP
nsPopupSetFrame::InsertFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList)
{
// need to rebuild all the springs.
for (int i=0; i < mSpringCount; i++)
mSprings[i].clear();
nsCOMPtr<nsIContent> frameChild;
aFrameList->GetContent(getter_AddRefs(frameChild));
nsCOMPtr<nsIAtom> tag;
nsresult rv;
frameChild->GetTag(*getter_AddRefs(tag));
if (tag && tag.get() == nsXULAtoms::popup) {
mPopupFrames.InsertFrames(nsnull, nsnull, aFrameList);
rv = GenerateDirtyReflowCommand(aPresContext, aPresShell);
} else {
rv = nsBoxFrame::InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList);
}
return rv;
}
NS_IMETHODIMP
nsPopupSetFrame::AppendFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
if (!aFrameList)
return NS_OK;
// need to rebuild all the springs.
for (int i=0; i < mSpringCount; i++)
mSprings[i].clear();
nsCOMPtr<nsIContent> frameChild;
aFrameList->GetContent(getter_AddRefs(frameChild));
nsCOMPtr<nsIAtom> tag;
nsresult rv;
frameChild->GetTag(*getter_AddRefs(tag));
if (tag && tag.get() == nsXULAtoms::popup) {
mPopupFrames.AppendFrames(nsnull, aFrameList);
rv = GenerateDirtyReflowCommand(aPresContext, aPresShell);
} else {
rv = nsBoxFrame::AppendFrames(aPresContext, aPresShell, aListName, aFrameList);
}
return rv;
}
NS_IMETHODIMP
nsPopupSetFrame::CreatePopup(nsIFrame* aElementFrame, nsIContent* aPopupContent,
PRInt32 aXPos, PRInt32 aYPos,
const nsString& aPopupType, const nsString& anAnchorAlignment,
const nsString& aPopupAlignment)
{
// Cache the element frame.
mElementFrame = aElementFrame;
// Show the popup at the specified position.
mXPos = aXPos;
mYPos = aYPos;
printf("X Pos: %d\n", mXPos);
printf("Y Pos: %d\n", mYPos);
if (!OnCreate(aPopupContent))
return NS_OK;
// Generate the popup.
MarkAsGenerated(aPopupContent);
// Now we'll have it in our child frame list.
// Now open the popup.
OpenPopup(PR_TRUE);
return NS_OK;
}
NS_IMETHODIMP
nsPopupSetFrame::HidePopup()
{
ActivatePopup(PR_FALSE);
return NS_OK;
}
NS_IMETHODIMP
nsPopupSetFrame::DestroyPopup()
{
OpenPopup(PR_FALSE);
return NS_OK;
}
void
nsPopupSetFrame::MarkAsGenerated(nsIContent* aPopupContent)
{
// Ungenerate all other popups in the set. No more than one can exist
// at any point in time.
PRInt32 childCount;
mContent->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> childContent;
mContent->ChildAt(i, *getter_AddRefs(childContent));
// Retrieve the menugenerated attribute.
nsAutoString value;
childContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::menugenerated,
value);
if (value == "true") {
// Ungenerate this element.
childContent->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::menugenerated,
PR_TRUE);
}
}
// Set our attribute, but only if we aren't already generated.
// Retrieve the menugenerated attribute.
nsAutoString value;
aPopupContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::menugenerated,
value);
if (value != "true") {
// Generate this element.
aPopupContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::menugenerated, "true",
PR_TRUE);
}
}
void
nsPopupSetFrame::OpenPopup(PRBool aActivateFlag)
{
if (aActivateFlag) {
ActivatePopup(PR_TRUE);
nsIFrame* activeChild = GetActiveChild();
nsCOMPtr<nsIMenuParent> childPopup = do_QueryInterface(activeChild);
UpdateDismissalListener(childPopup);
}
else {
if (!OnDestroy())
return;
// Unregister.
if (nsMenuFrame::mDismissalListener) {
nsMenuFrame::mDismissalListener->Unregister();
}
ActivatePopup(PR_FALSE);
}
}
void
nsPopupSetFrame::ActivatePopup(PRBool aActivateFlag)
{
nsCOMPtr<nsIContent> content;
GetActiveChildElement(getter_AddRefs(content));
if (content) {
if (aActivateFlag)
content->SetAttribute(kNameSpaceID_None, nsXULAtoms::menuactive, "true", PR_TRUE);
else content->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::menuactive, PR_TRUE);
}
}
PRBool
nsPopupSetFrame::OnCreate(nsIContent* aPopupContent)
{
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_MENU_CREATE;
if (aPopupContent) {
nsresult rv = aPopupContent->HandleDOMEvent(*mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status);
if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault )
return PR_FALSE;
}
return PR_TRUE;
}
PRBool
nsPopupSetFrame::OnDestroy()
{
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_MENU_DESTROY;
nsCOMPtr<nsIContent> content;
GetActiveChildElement(getter_AddRefs(content));
if (content) {
nsresult rv = content->HandleDOMEvent(*mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status);
if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault )
return PR_FALSE;
}
return PR_TRUE;
}
void
nsPopupSetFrame::GetActiveChildElement(nsIContent** aResult)
{
*aResult = nsnull;
nsIFrame* child = GetActiveChild();
if (child) {
child->GetContent(aResult);
}
}
void
nsPopupSetFrame::UpdateDismissalListener(nsIMenuParent* aMenuParent)
{
if (!nsMenuFrame::mDismissalListener) {
if (!aMenuParent)
return;
// Create the listener and attach it to the outermost window.
aMenuParent->CreateDismissalListener();
}
// Make sure the menu dismissal listener knows what the current
// innermost menu popup frame is.
nsMenuFrame::mDismissalListener->SetCurrentMenuParent(aMenuParent);
}

View File

@@ -0,0 +1,125 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
//
// nsPopupSetFrame
//
#ifndef nsPopupSetFrame_h__
#define nsPopupSetFrame_h__
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsCOMPtr.h"
#include "nsIPopupSetFrame.h"
#include "nsIAnonymousContentCreator.h"
#include "nsBoxFrame.h"
#include "nsFrameList.h"
#include "nsIMenuParent.h"
#include "nsITimer.h"
#include "nsITimerCallback.h"
#include "nsISupportsArray.h"
nsresult NS_NewPopupSetFrame(nsIFrame** aResult) ;
class nsPopupSetFrame : public nsBoxFrame, public nsIPopupSetFrame
{
public:
nsPopupSetFrame();
NS_DECL_ISUPPORTS
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
// The following four methods are all overridden so that the menu children
// can be stored in a separate list (so that they don't impact reflow of the
// actual menu item at all).
NS_IMETHOD FirstChild(nsIAtom* aListName,
nsIFrame** aFirstChild) const;
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex,
nsIAtom** aListName) const;
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
// Reflow methods
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus);
NS_IMETHOD Dirty(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild);
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame);
NS_IMETHOD CreatePopup(nsIFrame* aElementFrame, nsIContent* aPopupContent,
PRInt32 aXPos, PRInt32 aYPos,
const nsString& aPopupType, const nsString& anAnchorAlignment,
const nsString& aPopupAlignment);
NS_IMETHOD HidePopup();
NS_IMETHOD DestroyPopup();
PRBool OnCreate(nsIContent* aPopupContent);
PRBool OnDestroy();
void ActivatePopup(PRBool aActivateFlag);
void OpenPopup(PRBool aOpenFlag);
nsIFrame* GetActiveChild();
void GetActiveChildElement(nsIContent** aResult);
protected:
void MarkAsGenerated(nsIContent* aPopupContent);
void UpdateDismissalListener(nsIMenuParent* aMenuParent);
protected:
nsFrameList mPopupFrames;
nsIPresContext* mPresContext; // Our pres context.
nsIFrame* mElementFrame; // The frame that is having something popped up over it.
PRInt32 mXPos; // Active child's x position
PRInt32 mYPos; // Active child's y position
}; // class nsPopupSetFrame
#endif

View File

@@ -0,0 +1,813 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
static float STRIPE_SKEW = 1.0; // pixels
static int STRIPE_WIDTH = 20; // pixels
static int ANIMATION_INCREMENT = 4; // pixels
static int ANIMATION_SPEED = 50; // miliseconds
#include "nsINameSpaceManager.h"
#include "nsProgressMeterFrame.h"
#include "nsIStyleContext.h"
#include "nsCSSRendering.h"
#include "nsIContent.h"
#include "nsIPresContext.h"
#include "nsHTMLAtoms.h"
#include "nsXULAtoms.h"
#include "nsINameSpaceManager.h"
#include "nsITimerCallback.h"
#include "nsITimer.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsIReflowCommand.h"
#include "nsHTMLParts.h"
#include "nsIPresShell.h"
class StripeTimer : public nsITimerCallback {
public:
StripeTimer();
virtual ~StripeTimer();
NS_DECL_ISUPPORTS
void AddFrame(nsIPresContext* aPresContext, nsProgressMeterFrame* aFrame);
PRBool RemoveFrame(nsProgressMeterFrame* aFrame);
PRInt32 FrameCount();
void Start();
void Stop();
virtual void Notify(nsITimer *timer);
PRInt32 GetFrameData(nsProgressMeterFrame* aFrame);
struct FrameData {
nsIPresContext* mPresContext; // pres context associated with the frame
nsProgressMeterFrame* mFrame;
FrameData(nsIPresContext* aPresContext,
nsProgressMeterFrame* aFrame)
: mPresContext(aPresContext), mFrame(aFrame) {}
};
nsITimer* mTimer;
nsVoidArray mFrames;
};
static StripeTimer* gStripeAnimator;
StripeTimer::StripeTimer()
{
NS_INIT_REFCNT();
mTimer = nsnull;
}
StripeTimer::~StripeTimer()
{
Stop();
}
void StripeTimer::Start()
{
nsresult rv = NS_NewTimer(&mTimer);
if (NS_OK == rv) {
mTimer->Init(this, ANIMATION_SPEED);
}
}
void StripeTimer::Stop()
{
if (nsnull != mTimer) {
mTimer->Cancel();
NS_RELEASE(mTimer);
}
}
static NS_DEFINE_IID(kITimerCallbackIID, NS_ITIMERCALLBACK_IID);
NS_IMPL_ISUPPORTS(StripeTimer, kITimerCallbackIID);
PRInt32 StripeTimer::GetFrameData(nsProgressMeterFrame* aFrame)
{
PRInt32 i, n = mFrames.Count();
for (i = 0; i < n; i++) {
FrameData* frameData = (FrameData*) mFrames.ElementAt(i);
if (frameData->mFrame == aFrame) {
return i;
}
}
return -1;
}
void StripeTimer::AddFrame(nsIPresContext* aPresContext, nsProgressMeterFrame* aFrame) {
// see if the frame is already here.
if (GetFrameData(aFrame) > -1)
return;
// if not add it.
FrameData* frameData = new FrameData(aPresContext, aFrame);
mFrames.AppendElement(frameData);
if (1 == mFrames.Count()) {
Start();
}
}
PRBool StripeTimer::RemoveFrame(nsProgressMeterFrame* aFrame) {
PRBool rv = PR_FALSE;
PRInt32 i = GetFrameData(aFrame);
if (i > -1) {
FrameData* frameData = (FrameData*)mFrames.ElementAt(i);
rv = mFrames.RemoveElementAt(i);
delete frameData;
}
if (0 == mFrames.Count()) {
Stop();
}
return rv;
}
PRInt32 StripeTimer::FrameCount() {
return mFrames.Count();
}
void StripeTimer::Notify(nsITimer *timer)
{
// XXX hack to get auto-repeating timers; restart before doing
// expensive work so that time between ticks is more even
Stop();
Start();
PRInt32 i, n = mFrames.Count();
for (i = 0; i < n; i++) {
FrameData* frameData = (FrameData*) mFrames.ElementAt(i);
frameData->mFrame->animate();
// Determine damaged area and tell view manager to redraw it
nsPoint offset;
nsRect bounds;
frameData->mFrame->GetRect(bounds);
nsIView* view;
frameData->mFrame->GetOffsetFromView(frameData->mPresContext, offset, &view);
nsIViewManager* vm;
view->GetViewManager(vm);
bounds.x = offset.x;
bounds.y = offset.y;
vm->UpdateView(view, bounds, 0);
NS_RELEASE(vm);
}
}
//
// NS_NewToolbarFrame
//
// Creates a new Toolbar frame and returns it in |aNewFrame|
//
nsresult
NS_NewProgressMeterFrame ( nsIFrame** aNewFrame )
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsProgressMeterFrame* it = new nsProgressMeterFrame;
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
// it->SetFlags(aFlags);
*aNewFrame = it;
return NS_OK;
} // NS_NewProgressMeterFrame
//
// nsProgressMeterFrame cntr
//
// Init, if necessary
//
nsProgressMeterFrame :: nsProgressMeterFrame ( )
{
// if we haven't created the timer create it.
if (nsnull == gStripeAnimator) {
gStripeAnimator = new StripeTimer();
}
NS_ADDREF(gStripeAnimator);
mProgress = float(0.0);
mHorizontal = PR_TRUE;
mUndetermined = PR_FALSE;
mStripeOffset = STRIPE_WIDTH;
}
//
// nsProgressMeterFrame dstr
//
// Cleanup, if necessary
//
nsProgressMeterFrame :: ~nsProgressMeterFrame ( )
{
gStripeAnimator->RemoveFrame(this);
}
NS_IMETHODIMP
nsProgressMeterFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsLeafFrame::Init(aPresContext, aContent, aParent, aContext,
aPrevInFlow);
// get the value
nsAutoString value;
if ((NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, value)) &&
(value.Length() > 0)) {
setProgress(value);
}
// get the alignment
nsAutoString align;
mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, align);
setAlignment(align);
// get the mode
nsAutoString mode;
mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::mode, mode);
setMode(mode);
nsCOMPtr<nsIAtom> barPseudo ( dont_AddRef(NS_NewAtom(":progressmeter-stripe")) );
nsIStyleContext* barStyle = nsnull;
aPresContext.ProbePseudoStyleContextFor(aContent, barPseudo, aContext,
PR_FALSE, &barStyle);
mBarStyle = barStyle;
return rv;
}
void
nsProgressMeterFrame::setProgress(nsAutoString progress)
{
// convert to and integer
PRInt32 error;
PRInt32 v = progress.ToInteger(&error);
// adjust to 0 and 100
if (v < 0)
v = 0;
else if (v > 100)
v = 100;
// printf("ProgressMeter value=%d\n", v);
mProgress = float(v)/float(100);
}
void
nsProgressMeterFrame::setSize(nsAutoString sizeString, int& size, PRBool& isPercent)
{
// -1 means unset
size = -1;
int length = sizeString.Length();
if (length == 0)
return;
char w[100];
sizeString.ToCString(w,100);
if (w[length-1] == '%')
isPercent = PR_TRUE;
else
isPercent = PR_FALSE;
// convert to and integer
PRInt32 error;
PRInt32 v = sizeString.ToInteger(&error);
// adjust to 0 and 100
if (isPercent) {
if (v < 0)
v = 0;
else if (v > 100)
v = 100;
}
printf("size=%d\n", v);
size = v;
}
void
nsProgressMeterFrame::setAlignment(nsAutoString progress)
{
if (progress.EqualsIgnoreCase("vertical"))
mHorizontal = PR_FALSE;
else
mHorizontal = PR_TRUE;
}
void
nsProgressMeterFrame::setMode(nsAutoString mode)
{
if (mode.EqualsIgnoreCase("undetermined"))
mUndetermined = PR_TRUE;
else
mUndetermined = PR_FALSE;
}
//
// Paint
//
// Paint our background and border like normal frames, but before we draw the
// children, draw our grippies for each toolbar.
//
NS_IMETHODIMP
nsProgressMeterFrame :: Paint ( nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
const nsStyleDisplay* disp = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
// if we aren't visible then we are done.
if (!disp->mVisible)
return NS_OK;
// if we are visible then tell our superclass to paint
nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer);
// get our border
const nsStyleSpacing* spacing =
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
nsMargin border(0,0,0,0);
spacing->CalcBorderFor(this, border);
const nsStyleColor* colorStyle =
(const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color);
nscolor color = colorStyle->mColor;
// figure our twips convertion ratio
// float p2t;
// aPresContext.GetScaledPixelsToTwips(p2t);
// nscoord onePixel = NSIntPixelsToTwips(1, p2t);
// figure out our rectangle
nsRect rect(0,0,mRect.width, mRect.height);
// if its vertical then transform the coords to the X coordinate system
// and do our calculations there.
if (!mHorizontal)
rect = TransformYtoX(rect);
//CalcSize(aPresContext,rect.width,rect.height);
rect.x = border.left;
rect.y = border.top;
rect.width -= border.left*2;
rect.height -= border.top*2;
// paint the current progress in blue
PaintBar(aPresContext, aRenderingContext, rect, mProgress, color);
return NS_OK;
} // Paint
void
nsProgressMeterFrame :: PaintBar ( nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& rect,
float progress,
nscolor color) {
// if the bar is undetermined then use the whole progress area.
// if the bar is determined then figure out the current progress and make
// the bar only that percent of the full progress meter.
nsRect bar(rect);
if (!mUndetermined)
{
int p = (int)(bar.width*progress);
bar.width = p;
}
// fill the bar first then we will do the shading over it.
aRenderingContext.SetColor(color);
if (mHorizontal)
aRenderingContext.FillRect(bar);
else { // if we are vert then transfrom to the y cood system.
nsRect nbar = TransformXtoY(bar);
aRenderingContext.FillRect(nbar);
}
// draw the stripped barber shop if undetermined.
if (mUndetermined)
PaintBarStripped(aPresContext,aRenderingContext,bar, color);
else
PaintBarSolid(aPresContext,aRenderingContext,bar, color, 0);
}
nsRect
nsProgressMeterFrame::TransformXtoY(const nsRect& rect)
{
return nsRect(rect.y, mRect.height - (rect.x + rect.width), rect.height, rect.width);
}
nsRect
nsProgressMeterFrame::TransformYtoX(const nsRect& rect)
{
return nsRect(mRect.width - (rect.y + rect.height), rect.x, rect.height, rect.width);
}
nscolor
nsProgressMeterFrame::BrightenBy(nscolor c, PRUint8 amount)
{
PRUint8 r = NS_GET_R(c);
PRUint8 g = NS_GET_G(c);
PRUint8 b = NS_GET_B(c);
return NS_RGB(r+amount, g+amount, b+amount);
}
PRUint8
nsProgressMeterFrame::GetBrightness(nscolor c)
{
// get the biggest rgb component;
PRUint8 r = NS_GET_R(c);
PRUint8 g = NS_GET_G(c);
PRUint8 b = NS_GET_B(c);
PRUint8 biggest = r;
if (r > g && r > b)
biggest = r;
else if (g > r && g > b)
biggest = g;
else if (b > r && b > g)
biggest = b;
return biggest;
}
void
nsProgressMeterFrame::PaintBarSolid(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext,
const nsRect& rect, nscolor color, float skew)
{
// figure out a pixel size
float p2t;
aPresContext.GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
// how many pixel lines will fit?
int segments = (rect.height/2) / onePixel;
// get the skew in pixels;
int skewedPixels = int(skew * onePixel);
// we will draw from the top to center and from the bottom to center at the same time
// so we need 2 rects one for the top and one for the bottom
// top.
nsRect tr(rect);
tr.height= onePixel;
// bottom
nsRect br(rect);
br.height = onePixel;
br.y = rect.y + 2*segments*onePixel;
br.x = rect.x + 2*segments*skewedPixels;
// get the brightness of the color
PRUint8 brightness = GetBrightness(color);
// we need to figure out how bright we can get.
PRUint8 units = (255 - brightness)/segments;
// get a color we can set
nscolor c(color);
for (int i=0; i <= segments; i++)
{
// set the color and fill the top and bottom lines
aRenderingContext.SetColor(c);
if (mHorizontal) {
aRenderingContext.FillRect(tr);
aRenderingContext.FillRect(br);
} else {
aRenderingContext.FillRect(TransformXtoY(tr));
aRenderingContext.FillRect(TransformXtoY(br));
}
// brighten the color
c = BrightenBy(c, units);
// move one line down
tr.x += skewedPixels;
tr.y += onePixel;
// move one line up
br.y -= onePixel;
br.x -= skewedPixels;
}
}
void
nsProgressMeterFrame::PaintBarStripped(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext,
const nsRect& r, nscolor color)
{
// get stripe color from the style system
nsCOMPtr<nsIStyleContext> style (mBarStyle) ;
nscolor altColor = NS_RGB(128,128,128);
// if we got a style then get the color from it
if (style != 0)
{
const nsStyleColor* barColor = (const nsStyleColor*)style->GetStyleData(eStyleStruct_Color);
altColor = barColor->mColor;
}
float skew = STRIPE_SKEW;
float stripeWidth = float(STRIPE_WIDTH);
nsRect rect(r);
PRBool clipState;
// Clip so we don't render outside the inner rect
aRenderingContext.PushState();
if (mHorizontal)
aRenderingContext.SetClipRect(rect, nsClipCombine_kIntersect, clipState);
else
aRenderingContext.SetClipRect(TransformXtoY(rect), nsClipCombine_kIntersect, clipState);
float p2t;
aPresContext.GetScaledPixelsToTwips(&p2t);
// nscoord onePixel = NSIntPixelsToTwips(1, p2t);
int stripeWidthInTwips = (int)(stripeWidth * p2t);
int offset = int(float(r.height) * skew);
//make things a little bigger and just clip them
rect.width += offset*2;
rect.x -= (offset + int(float(mStripeOffset)*p2t));
int stripes = rect.width / (stripeWidthInTwips/2) + 2;
nsRect sr(rect.x,rect.y,stripeWidthInTwips,rect.height);
PRBool onoff = PR_FALSE;
nscolor c;
for (int i=0; i < stripes; i++)
{
if (onoff)
c = color;
else
c = altColor;
PaintBarSolid(aPresContext,aRenderingContext,sr, c, skew);
sr.x += (stripeWidthInTwips/2);
onoff = !onoff;
}
aRenderingContext.PopState(clipState);
}
void
nsProgressMeterFrame::animate()
{
mStripeOffset -= ANIMATION_INCREMENT;
// printf("animate=%d\n", mStripeOffset);
if (mStripeOffset < 0)
mStripeOffset = STRIPE_WIDTH;
}
//
// Reflow
//
// Handle moving children around.
//
NS_IMETHODIMP
nsProgressMeterFrame :: Reflow ( nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
if (eReflowReason_Incremental == aReflowState.reason) {
nsIFrame* targetFrame;
// See if it's targeted at us
aReflowState.reflowCommand->GetTarget(targetFrame);
if (this == targetFrame) {
Invalidate(&aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE);
}
}
if (mUndetermined)
gStripeAnimator->AddFrame(&aPresContext, this);
else
gStripeAnimator->RemoveFrame(this);
return nsLeafFrame::Reflow ( aPresContext, aDesiredSize, aReflowState, aStatus );
} // Reflow
void
nsProgressMeterFrame::GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize)
{
CalcSize(*aPresContext,aDesiredSize.width,aDesiredSize.height);
// if the width is set use it
if (NS_INTRINSICSIZE != aReflowState.mComputedWidth)
aDesiredSize.width = aReflowState.mComputedWidth;
// if the height is set use it
if (NS_INTRINSICSIZE != aReflowState.mComputedHeight)
aDesiredSize.height = aReflowState.mComputedHeight;
}
void
nsProgressMeterFrame::CalcSize(nsIPresContext& aPresContext, int& width, int& height)
{
// make sure we convert to twips.
float p2t;
aPresContext.GetScaledPixelsToTwips(&p2t);
if (mHorizontal) {
width = (int)(100 * p2t);
height = (int)(16 * p2t);
} else {
height = (int)(100 * p2t);
width = (int)(16 * p2t);
}
}
NS_IMETHODIMP
nsProgressMeterFrame::AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint)
{
nsresult rv = nsLeafFrame::AttributeChanged(aPresContext, aChild,
aNameSpaceID, aAttribute, aHint);
if (NS_OK != rv) {
return rv;
}
// did the progress change?
if (nsHTMLAtoms::value == aAttribute) {
nsAutoString newValue;
// get attribute and set it
aChild->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, newValue);
setProgress(newValue);
Redraw(aPresContext);
} else if (nsXULAtoms::mode == aAttribute) {
nsAutoString newValue;
aChild->GetAttribute(kNameSpaceID_None, nsXULAtoms::mode, newValue);
setMode(newValue);
// needs to reflow so we start the timer.
if (aHint != NS_STYLE_HINT_REFLOW)
Reflow(aPresContext);
} else if (nsHTMLAtoms::align == aAttribute) {
nsAutoString newValue;
// get attribute and set it
aChild->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, newValue);
setAlignment(newValue);
if (aHint != NS_STYLE_HINT_REFLOW)
Reflow(aPresContext);
}
return NS_OK;
}
void
nsProgressMeterFrame::Reflow(nsIPresContext* aPresContext)
{
// reflow
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
nsCOMPtr<nsIReflowCommand> reflowCmd;
nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), this,
nsIReflowCommand::StyleChanged);
if (NS_SUCCEEDED(rv))
shell->AppendReflowCommand(reflowCmd);
}
void
nsProgressMeterFrame::Redraw(nsIPresContext* aPresContext)
{
nsRect frameRect;
GetRect(frameRect);
nsRect rect(0, 0, frameRect.width, frameRect.height);
Invalidate(aPresContext, rect, PR_TRUE);
}
NS_IMETHODIMP
nsProgressMeterFrame::GetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext** aStyleContext) const
{
NS_PRECONDITION(nsnull != aStyleContext, "null OUT parameter pointer");
if (aIndex < 0) {
return NS_ERROR_INVALID_ARG;
}
*aStyleContext = nsnull;
switch (aIndex) {
case NS_PROGRESS_METER_STRIPE_CONTEXT_INDEX:
*aStyleContext = mBarStyle;
NS_IF_ADDREF(*aStyleContext);
break;
default:
return NS_ERROR_INVALID_ARG;
}
return NS_OK;
}
NS_IMETHODIMP
nsProgressMeterFrame::SetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext* aStyleContext)
{
if (aIndex < 0) {
return NS_ERROR_INVALID_ARG;
}
switch (aIndex) {
case NS_PROGRESS_METER_STRIPE_CONTEXT_INDEX:
mBarStyle = aStyleContext;
break;
}
return NS_OK;
}

View File

@@ -0,0 +1,140 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
/**
Eric D Vaughan.
A simple progress meter.
Attributes:
value: A number between 0% adn 100%
align: horizontal, or vertical
mode: determined, undetermined (one shows progress other shows animated candy cane)
Style:
Bar gets its color from the color style
Alternating stripes can be set with the seudo style:
:PROGRESSMETER-STRIPE {
color: gray
}
**/
#include "nsLeafFrame.h"
#include "nsColor.h"
#include "nsCOMPtr.h"
#include "nsIStyleContext.h"
#include "nsIPresContext.h"
#include "prtypes.h"
class nsIPresContext;
class nsIStyleContext;
#define NS_PROGRESS_METER_STRIPE_CONTEXT_INDEX 1
class nsProgressMeterFrame : public nsLeafFrame
{
public:
friend nsresult NS_NewProgressMeterFrame(nsIFrame** aNewFrame);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
// nsIHTMLReflow overrides
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint);
NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext** aStyleContext) const;
NS_IMETHOD SetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext* aStyleContext);
virtual void animate();
virtual void Reflow(nsIPresContext* aPresContext);
virtual void Redraw(nsIPresContext* aPresContext);
protected:
nsProgressMeterFrame();
virtual ~nsProgressMeterFrame();
virtual void GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize);
virtual void CalcSize(nsIPresContext& aPresContext, int& width, int& height);
virtual void PaintBar ( nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& rect,
float progress,
nscolor color);
virtual void PaintBarStripped(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext,
const nsRect& rect, nscolor color);
virtual void PaintBarSolid(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext,
const nsRect& rect, nscolor color, float skew);
virtual nscolor BrightenBy(nscolor color, PRUint8 amount);
virtual PRUint8 GetBrightness(nscolor c);
virtual nsRect TransformXtoY(const nsRect& rect);
virtual nsRect TransformYtoX(const nsRect& rect);
// pass-by-value not allowed for a coordinator because it corresponds 1-to-1
// with an element in the UI.
nsProgressMeterFrame ( const nsProgressMeterFrame& aFrame ) ; // DO NOT IMPLEMENT
nsProgressMeterFrame& operator= ( const nsProgressMeterFrame& aFrame ) ; // DO NOT IMPLEMENT
private:
void setProgress(nsAutoString progress);
void setAlignment(nsAutoString alignment);
void setMode(nsAutoString mode);
void setSize(nsAutoString s, int& size, PRBool& isPercent);
nsCOMPtr<nsIStyleContext> mBarStyle;
float mProgress;
PRBool mHorizontal;
PRBool mUndetermined;
int mStripeOffset;
}; // class nsProgressMeterFrame

View File

@@ -0,0 +1,90 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
#include "nsRepeatService.h"
#define INITAL_REPEAT_DELAY 250
#define REPEAT_DELAY 50
nsRepeatService* nsRepeatService::gInstance = nsnull;
nsRepeatService::nsRepeatService()
{
}
nsRepeatService::~nsRepeatService()
{
mCallback = nsnull;
Stop();
}
nsRepeatService*
nsRepeatService::GetInstance()
{
if (!gInstance) {
gInstance = new nsRepeatService();
gInstance->mRefCnt = 1;
}
return gInstance;
}
void nsRepeatService::Start(nsITimerCallback* aCallback)
{
mCallback = aCallback;
nsresult rv = NS_NewTimer(getter_AddRefs(mRepeatTimer));
if (NS_OK == rv) {
mRepeatTimer->Init(this, INITAL_REPEAT_DELAY);
}
}
void nsRepeatService::Stop()
{
//printf("Stopping repeat timer\n");
if (mRepeatTimer) {
mRepeatTimer->Cancel();
mRepeatTimer = nsnull;
mCallback = nsnull;
}
}
void nsRepeatService::Notify(nsITimer *timer)
{
// if the repeat delay is the initial one reset it.
if (mRepeatTimer) {
mRepeatTimer->Cancel();
NS_NewTimer(getter_AddRefs(mRepeatTimer));
mRepeatTimer->Init(this, REPEAT_DELAY);
}
mCallback->Notify(timer);
}
static NS_DEFINE_IID(kITimerCallbackIID, NS_ITIMERCALLBACK_IID);
NS_IMPL_ISUPPORTS(nsRepeatService, kITimerCallbackIID);

View File

@@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
//
// nsRepeatService
//
#ifndef nsRepeatService_h__
#define nsRepeatService_h__
#include "nsCOMPtr.h"
#include "nsITimerCallback.h"
#include "nsITimer.h"
class nsITimer;
class nsRepeatService : public nsITimerCallback
{
public:
virtual void Notify(nsITimer *timer);
void Start(nsITimerCallback* aCallback);
void Stop();
static nsRepeatService* GetInstance();
NS_DECL_ISUPPORTS
virtual ~nsRepeatService();
protected:
nsRepeatService();
private:
nsCOMPtr<nsITimerCallback> mCallback;
nsCOMPtr<nsITimer> mRepeatTimer;
static nsRepeatService* gInstance;
}; // class nsRepeatService
#endif

View File

@@ -0,0 +1,244 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
#include "nsScrollbarButtonFrame.h"
#include "nsIStyleContext.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
#include "nsCOMPtr.h"
#include "nsHTMLIIDs.h"
#include "nsUnitConversion.h"
#include "nsINameSpaceManager.h"
#include "nsHTMLAtoms.h"
#include "nsXULAtoms.h"
#include "nsIReflowCommand.h"
#include "nsSliderFrame.h"
#include "nsRepeatService.h"
//
// NS_NewToolbarFrame
//
// Creates a new Toolbar frame and returns it in |aNewFrame|
//
nsresult
NS_NewScrollbarButtonFrame ( nsIFrame** aNewFrame )
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsScrollbarButtonFrame* it = new nsScrollbarButtonFrame;
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
} // NS_NewScrollBarButtonFrame
/*
nsScrollbarButtonFrame::nsScrollbarButtonFrame()
{
}*/
static NS_DEFINE_IID(kITimerCallbackIID, NS_ITIMERCALLBACK_IID);
NS_IMETHODIMP
nsScrollbarButtonFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (aIID.Equals(kITimerCallbackIID)) {
*aInstancePtr = (void*)(nsITimerCallback*) this;
NS_ADDREF_THIS();
return NS_OK;
}
return nsTitledButtonFrame::QueryInterface(aIID, aInstancePtr);
}
NS_IMETHODIMP
nsScrollbarButtonFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
// XXX hack until handle release is actually called in nsframe.
if (aEvent->message == NS_MOUSE_EXIT|| aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
HandleRelease(aPresContext, aEvent, aEventStatus);
return nsTitledButtonFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
NS_IMETHODIMP
nsScrollbarButtonFrame::HandlePress(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
nsRepeatService::GetInstance()->Start(this);
return NS_OK;
}
NS_IMETHODIMP
nsScrollbarButtonFrame::HandleRelease(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
nsRepeatService::GetInstance()->Stop();
return NS_OK;
}
void nsScrollbarButtonFrame::Notify(nsITimer *timer)
{
MouseClicked();
}
void
nsScrollbarButtonFrame::MouseClicked(nsIPresContext& aPresContext)
{
MouseClicked();
}
void
nsScrollbarButtonFrame::MouseClicked()
{
// when we are clicked either increment or decrement the slider position.
// get the scrollbar control
nsIFrame* scrollbar;
GetParentWithTag(nsXULAtoms::scrollbar, this, scrollbar);
if (scrollbar == nsnull)
return;
// get the scrollbars content node
nsCOMPtr<nsIContent> content;
scrollbar->GetContent(getter_AddRefs(content));
// get the current pos
PRInt32 curpos = nsSliderFrame::GetCurrentPosition(content);
// get the max pos
PRInt32 maxpos = nsSliderFrame::GetMaxPosition(content);
// get the increment amount
PRInt32 increment = nsSliderFrame::GetIncrement(content);
nsString value;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, value))
{
// if our class is DecrementButton subtract the current pos by increment amount
// if our class is IncrementButton increment the current pos by the decrement amount
if (value.Equals("decrement"))
curpos -= increment;
else if (value.Equals("increment"))
curpos += increment;
// make sure the current positon is between the current and max positions
if (curpos < 0)
curpos = 0;
else if (curpos > maxpos)
curpos = maxpos;
// set the current position of the slider.
char v[100];
sprintf(v, "%d", curpos);
content->SetAttribute(kNameSpaceID_None, nsXULAtoms::curpos, v, PR_TRUE);
}
}
nsresult
nsScrollbarButtonFrame::GetChildWithTag(nsIAtom* atom, nsIFrame* start, nsIFrame*& result)
{
// recursively search our children
nsIFrame* childFrame;
start->FirstChild(nsnull, &childFrame);
while (nsnull != childFrame)
{
// get the content node
nsCOMPtr<nsIContent> child;
childFrame->GetContent(getter_AddRefs(child));
if (child) {
// see if it is the child
nsIAtom* tag = nsnull;
child->GetTag(tag);
if (tag == atom)
{
result = childFrame;
return NS_OK;
}
}
// recursive search the child
GetChildWithTag(atom, childFrame, result);
if (result != nsnull)
return NS_OK;
nsresult rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
}
result = nsnull;
return NS_OK;
}
nsresult
nsScrollbarButtonFrame::GetParentWithTag(nsIAtom* toFind, nsIFrame* start, nsIFrame*& result)
{
while(nsnull != start)
{
start->GetParent(&start);
if (start) {
// get the content node
nsCOMPtr<nsIContent> child;
start->GetContent(getter_AddRefs(child));
nsIAtom* atom;
if (child && child->GetTag(atom) == NS_OK && atom == toFind) {
result = start;
return NS_OK;
}
}
}
result = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsScrollbarButtonFrame::Destroy(nsIPresContext& aPresContext)
{
// Ensure our repeat service isn't going... it's possible that a scrollbar can disappear out
// from under you while you're in the process of scrolling.
nsRepeatService::GetInstance()->Stop();
return nsTitledButtonFrame::Destroy(aPresContext);
}

View File

@@ -0,0 +1,86 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
/**
Eric D Vaughan
This class lays out its children either vertically or horizontally
**/
#ifndef nsScrollbarButtonFrame_h___
#define nsScrollbarButtonFrame_h___
#include "nsTitledButtonFrame.h"
#include "nsITimerCallback.h"
class nsSliderFrame;
class nsScrollbarButtonFrame : public nsTitledButtonFrame,
public nsITimerCallback
{
public:
// Overrides
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
friend nsresult NS_NewScrollBarButtonFrame(nsIFrame** aNewFrame);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
static nsresult GetChildWithTag(nsIAtom* atom, nsIFrame* start, nsIFrame*& result);
static nsresult GetParentWithTag(nsIAtom* atom, nsIFrame* start, nsIFrame*& result);
NS_IMETHOD HandlePress(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleMultiplePress(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus) { return NS_OK; }
NS_IMETHOD HandleDrag(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus) { return NS_OK; }
NS_IMETHOD HandleRelease(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
virtual void Notify(nsITimer *timer);
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; }
NS_IMETHOD_(nsrefcnt) Release(void) { return NS_OK; }
protected:
virtual void MouseClicked(nsIPresContext& aPresContext);
virtual void MouseClicked();
}; // class nsTabFrame
#endif

View File

@@ -0,0 +1,390 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
#include "nsScrollbarFrame.h"
#include "nsScrollbarButtonFrame.h"
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsISupportsArray.h"
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsINameSpaceManager.h"
#include "nsIXMLContent.h"
#include "nsIDOMDocument.h"
#include "nsIDocument.h"
#include "nsIDOMElement.h"
#include "nsXMLElement.h"
#include "nsIStyledContent.h"
#include "nsGenericElement.h"
#include "nsIStyleRule.h"
#include "nsHTMLValue.h"
#include "nsIAnonymousContent.h"
#include "nsIView.h"
static NS_DEFINE_IID(kIAnonymousContentCreatorIID, NS_IANONYMOUS_CONTENT_CREATOR_IID);
static NS_DEFINE_IID(kIStyledContentIID, NS_ISTYLEDCONTENT_IID);
static NS_DEFINE_IID(kIAnonymousContentIID, NS_IANONYMOUS_CONTENT_IID);
class AnonymousElement : public nsXMLElement, nsIStyledContent, nsIAnonymousContent
{
public:
AnonymousElement(nsIAtom *aTag):nsXMLElement(aTag) {}
// nsIStyledContent
NS_IMETHOD GetID(nsIAtom*& aResult) const;
NS_IMETHOD GetClasses(nsVoidArray& aArray) const;
NS_IMETHOD HasClass(nsIAtom* aClass) const;
NS_IMETHOD GetContentStyleRules(nsISupportsArray* aRules);
NS_IMETHOD GetInlineStyleRules(nsISupportsArray* aRules);
NS_IMETHOD GetMappedAttributeImpact(const nsIAtom* aAttribute,
PRInt32& aHint) const;
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
NS_IMPL_ICONTENT_USING_GENERIC(mInner)
// NS_IMPL_ICONTENT_USING_GENERIC_DOM_DATA(mInner)
};
NS_IMETHODIMP
AnonymousElement::SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const {
return this->nsXMLElement::SizeOf(aSizer, aResult);
}
/*
NS_IMETHODIMP
AnonymousElement::GetTag(nsIAtom*& aResult) const
{
return mInner.GetTag(aResult);
}
NS_IMETHODIMP
AnonymousElement::List(FILE* out, PRInt32 aIndent) const
{
NS_PRECONDITION(nsnull != mInner.mDocument, "bad content");
PRInt32 indx;
for (indx = aIndent; --indx >= 0; ) fputs(" ", out);
fprintf(out, "Comment refcount=%d<", mRefCnt);
nsAutoString tmp;
mInner.ToCString(tmp, 0, mInner.mText.GetLength());
fputs(tmp, out);
fputs(">\n", out);
return mInner.List(out, aIndent);
}
*/
NS_IMETHODIMP
AnonymousElement::HandleDOMEvent(nsIPresContext& aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus& aEventStatus)
{
/*
// if our parent is not anonymous then we don't want to bubble the event
// so lets set our parent in nsnull to prevent it. Then we will set it
// back.
nsIContent* parent = nsnull;
GetParent(parent);
nsCOMPtr<nsIAnonymousContent> anonymousParent(do_QueryInterface(parent));
if (!anonymousParent)
SetParent(nsnull);
*/
nsresult rv = mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags, aEventStatus);
/*
if (!anonymousParent)
SetParent(parent);
*/
return rv;
}
// nsIStyledContent Implementation
NS_IMETHODIMP
AnonymousElement::GetID(nsIAtom*& aResult) const
{
/*
nsAutoString value;
GetAttribute(kNameSpaceID_None, kIdAtom, value);
aResult = NS_NewAtom(value); // The NewAtom call does the AddRef.
*/
aResult = nsnull;
return NS_OK;
}
NS_IMETHODIMP
AnonymousElement::GetClasses(nsVoidArray& aArray) const
{
return NS_OK;
}
NS_IMETHODIMP
AnonymousElement::HasClass(nsIAtom* aClass) const
{
return NS_COMFALSE;
}
NS_IMETHODIMP
AnonymousElement::GetContentStyleRules(nsISupportsArray* aRules)
{
return NS_OK;
}
NS_IMETHODIMP
AnonymousElement::GetInlineStyleRules(nsISupportsArray* aRules)
{
// we don't currently support the style attribute
return NS_OK;
}
NS_IMETHODIMP
AnonymousElement::GetMappedAttributeImpact(const nsIAtom* aAttribute,
PRInt32& aHint) const
{
aHint = NS_STYLE_HINT_CONTENT; // we never map attribtes to style
return NS_OK;
}
NS_IMETHODIMP
AnonymousElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (aIID.Equals(kIStyledContentIID)) {
nsIStyledContent* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
} else if (aIID.Equals(kIAnonymousContentIID)) {
nsIAnonymousContent* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
return nsXMLElement::QueryInterface(aIID, aInstancePtr);
}
NS_IMPL_ADDREF_INHERITED(AnonymousElement, nsXMLElement)
NS_IMPL_RELEASE_INHERITED(AnonymousElement, nsXMLElement)
nsresult NS_CreateAnonymousNode(nsIContent* aParent, nsIAtom* aTag, PRInt32 aNameSpaceId, nsCOMPtr<nsIContent>& aNewNode)
{
// create the xml element
nsCOMPtr<nsIXMLContent> content;
//NS_NewXMLElement(getter_AddRefs(content), aTag);
content = new AnonymousElement(aTag);
content->SetNameSpaceID(aNameSpaceId);
aNewNode = content;
/*
nsCOMPtr<nsIDocument> document;
aParent->GetDocument(*getter_AddRefs(document));
nsCOMPtr<nsIDOMDocument> domDocument(do_QueryInterface(document));
nsCOMPtr<nsIDOMElement> element;
nsString name;
aTag->ToString(name);
domDocument->CreateElement(name, getter_AddRefs(element));
aNewNode = do_QueryInterface(element);
*/
return NS_OK;
}
//
// NS_NewToolbarFrame
//
// Creates a new Toolbar frame and returns it in |aNewFrame|
//
nsresult
NS_NewScrollbarFrame ( nsIFrame** aNewFrame )
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsScrollbarFrame* it = new nsScrollbarFrame;
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
} // NS_NewScrollbarFrame
/**
* Anonymous interface
*/
NS_IMETHODIMP
nsScrollbarFrame::CreateAnonymousContent(nsISupportsArray& aAnonymousChildren)
{
// if not content the create some anonymous content
PRInt32 count = 0;
mContent->ChildCount(count);
if (count == 0) {
nsCOMPtr<nsIContent> content;
NS_CreateAnonymousNode(mContent, nsXULAtoms::scrollbarbutton, nsXULAtoms::nameSpaceID, content);
content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, "decrement", PR_FALSE);
aAnonymousChildren.AppendElement(content);
NS_CreateAnonymousNode(mContent, nsXULAtoms::slider, nsXULAtoms::nameSpaceID, content);
content->SetAttribute(kNameSpaceID_None, nsXULAtoms::flex, "1", PR_FALSE);
aAnonymousChildren.AppendElement(content);
NS_CreateAnonymousNode(mContent, nsXULAtoms::scrollbarbutton, nsXULAtoms::nameSpaceID, content);
content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, "increment", PR_FALSE);
aAnonymousChildren.AppendElement(content);
}
return NS_OK;
}
NS_IMETHODIMP
nsScrollbarFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
CreateViewForFrame(aPresContext,this,aContext,PR_TRUE);
nsIView* view;
GetView(&aPresContext, &view);
view->SetContentTransparency(PR_TRUE);
return rv;
}
NS_IMETHODIMP
nsScrollbarFrame::AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint)
{
nsresult rv = nsBoxFrame::AttributeChanged(aPresContext, aChild,
aNameSpaceID, aAttribute, aHint);
// if the current position changes
if ( aAttribute == nsXULAtoms::curpos ||
aAttribute == nsXULAtoms::maxpos ||
aAttribute == nsXULAtoms::pageincrement ||
aAttribute == nsXULAtoms::increment) {
// tell the slider its attribute changed so it can
// update itself
nsIFrame* slider;
nsScrollbarButtonFrame::GetChildWithTag(nsXULAtoms::slider, this, slider);
if (slider)
slider->AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aHint);
}
return rv;
}
NS_IMETHODIMP
nsScrollbarFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(kIAnonymousContentCreatorIID)) {
*aInstancePtr = (void*)(nsIAnonymousContentCreator*) this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIStyledContentIID)) {
*aInstancePtr = (void*)(nsIStyledContent*) this;
NS_ADDREF_THIS();
return NS_OK;
}
return nsBoxFrame::QueryInterface(aIID, aInstancePtr);
}
NS_IMETHODIMP
nsScrollbarFrame::HandlePress(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
return NS_OK;
}
NS_IMETHODIMP
nsScrollbarFrame::HandleMultiplePress(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
return NS_OK;
}
NS_IMETHODIMP
nsScrollbarFrame::HandleDrag(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
return NS_OK;
}
NS_IMETHODIMP
nsScrollbarFrame::HandleRelease(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
return NS_OK;
}

View File

@@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
//
// nsScrollbarFrame
//
#ifndef nsScrollbarFrame_h__
#define nsScrollbarFrame_h__
#include "nsBoxFrame.h"
#include "nsIAnonymousContentCreator.h"
class nsISupportsArray;
nsresult NS_NewScrollbarFrame(nsIFrame** aResult) ;
class nsScrollbarFrame : public nsBoxFrame,
public nsIAnonymousContentCreator
{
public:
nsScrollbarFrame() {}
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const {
return MakeFrameName("ScrollbarFrame", aResult);
}
#endif
// nsIFrame overrides
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint);
// nsIAnonymousConentCreator
NS_IMETHOD CreateAnonymousContent(nsISupportsArray& aAnonymousItems);
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
NS_IMETHOD HandlePress(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleMultiplePress(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleDrag(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleRelease(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
}; // class nsScrollbarFrame
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,234 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
//
// nsSliderFrame
//
#ifndef nsSliderFrame_h__
#define nsSliderFrame_h__
#include "nsHTMLContainerFrame.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsCOMPtr.h"
#include "nsIDOMMouseListener.h"
#include "nsIAnonymousContentCreator.h"
#include "nsITimerCallback.h"
class nsString;
class nsIScrollbarListener;
class nsISupportsArray;
class nsITimer;
#define INITAL_REPEAT_DELAY 500
#define REPEAT_DELAY 50
nsresult NS_NewSliderFrame(nsIFrame** aResult) ;
class nsSliderFrame : public nsHTMLContainerFrame,
nsIDOMMouseListener,
nsIAnonymousContentCreator,
nsITimerCallback
{
public:
nsSliderFrame();
virtual ~nsSliderFrame();
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const {
return MakeFrameName("SliderFrame", aResult);
}
#endif
// nsIFrame overrides
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint);
virtual nsresult CurrentPositionChanged(nsIPresContext* aPresContext);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* asPrevInFlow);
NS_IMETHOD CreateAnonymousContent(nsISupportsArray& aAnonymousItems);
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint, nsIFrame** aFrame);
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
/**
* Processes a mouse down event
* @param aMouseEvent @see nsIDOMEvent.h
* @returns whether the event was consumed or ignored. @see nsresult
*/
virtual nsresult MouseDown(nsIDOMEvent* aMouseEvent);
/**
* Processes a mouse up event
* @param aMouseEvent @see nsIDOMEvent.h
* @returns whether the event was consumed or ignored. @see nsresult
*/
virtual nsresult MouseUp(nsIDOMEvent* aMouseEvent);
/**
* Processes a mouse click event
* @param aMouseEvent @see nsIDOMEvent.h
* @returns whether the event was consumed or ignored. @see nsresult
*
*/
virtual nsresult MouseClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }
/**
* Processes a mouse click event
* @param aMouseEvent @see nsIDOMEvent.h
* @returns whether the event was consumed or ignored. @see nsresult
*
*/
virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }
/**
* Processes a mouse enter event
* @param aMouseEvent @see nsIDOMEvent.h
* @returns whether the event was consumed or ignored. @see nsresult
*/
virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; }
/**
* Processes a mouse leave event
* @param aMouseEvent @see nsIDOMEvent.h
* @returns whether the event was consumed or ignored. @see nsresult
*/
virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent) { return NS_OK; }
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
virtual nsresult HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; }
static PRInt32 GetCurrentPosition(nsIContent* content);
static PRInt32 GetMaxPosition(nsIContent* content);
static PRInt32 GetIncrement(nsIContent* content);
static PRInt32 GetPageIncrement(nsIContent* content);
static PRInt32 GetIntegerAttribute(nsIContent* content, nsIAtom* atom, PRInt32 defaultValue);
static PRInt32 IsHorizontal(nsIContent* content);
void SetScrollbarListener(nsIScrollbarListener* aListener);
NS_IMETHOD HandlePress(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleMultiplePress(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus) { return NS_OK; }
NS_IMETHOD HandleDrag(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus) { return NS_OK; }
NS_IMETHOD HandleRelease(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
virtual void Notify(nsITimer *timer);
protected:
virtual nsresult ReflowThumb(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame* thumbFrame,
nsSize available,
nsSize computed);
virtual PRIntn GetSkipSides() const { return 0; }
private:
nsIContent* GetScrollBar();
void PageUpDown(nsIFrame* aThumbFrame, nscoord change);
void SetCurrentPosition(nsIContent* scrollbar, nsIFrame* aThumbFrame, nscoord pos);
NS_IMETHOD DragThumb(nsIPresContext* aPresContext, PRBool aGrabMouseEvents);
void AddListener();
void RemoveListener();
PRBool isDraggingThumb(nsIPresContext* aPresContext);
float mRatio;
nscoord mDragStartPx;
nscoord mThumbStart;
PRInt32 mCurPos;
nsIScrollbarListener* mScrollbarListener;
// XXX Hack
nsIPresContext* mPresContext; // weak reference
static nscoord gChange;
}; // class nsSliderFrame
#endif

View File

@@ -0,0 +1,111 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
#include "nsSpinnerFrame.h"
#include "nsIContent.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsCSSRendering.h"
#include "nsINameSpaceManager.h"
//
// NS_NewSpinnerFrame
//
// Wrapper for creating a new spinner
//
nsresult
NS_NewSpinnerFrame(nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsSpinnerFrame* it = new nsSpinnerFrame;
if ( !it )
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
}
//
// nsSpinnerFrame cntr
//
nsSpinnerFrame::nsSpinnerFrame()
{
} // cntr
//
// Paint
//
// Overidden to handle ???
//
NS_METHOD
nsSpinnerFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
return nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
}
//
// GetDesiredSize
//
// For now, be as big as CSS wants us to be, or some small default size.
//
void
nsSpinnerFrame :: GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredLayoutSize)
{
const int CSS_NOTSET = -1;
nsSize styleSize;
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
styleSize.width = aReflowState.mComputedWidth;
}
else {
styleSize.width = CSS_NOTSET;
}
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) {
styleSize.height = aReflowState.mComputedHeight;
}
else {
styleSize.height = CSS_NOTSET;
}
// subclasses should always override this method, but if not and no css, make it small
aDesiredLayoutSize.width = (styleSize.width > CSS_NOTSET) ? styleSize.width : 200;
aDesiredLayoutSize.height = (styleSize.height > CSS_NOTSET) ? styleSize.height : 200;
aDesiredLayoutSize.ascent = aDesiredLayoutSize.height;
aDesiredLayoutSize.descent = 0;
if (aDesiredLayoutSize.maxElementSize) {
aDesiredLayoutSize.maxElementSize->width = aDesiredLayoutSize.width;
aDesiredLayoutSize.maxElementSize->height = aDesiredLayoutSize.height;
}
} // GetDesiredSize

View File

@@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
//
// nsSpinnerFrame
//
#ifndef nsSpinnerFrame_h__
#define nsSpinnerFrame_h__
#include "nsLeafFrame.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsCOMPtr.h"
class nsString;
nsresult NS_NewSpinnerFrame(nsIFrame** aResult) ;
class nsSpinnerFrame : public nsLeafFrame
{
public:
nsSpinnerFrame();
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const {
return MakeFrameName("SpinnerFrame", aResult);
}
#endif
// nsIFrame overrides
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
protected:
virtual void GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize) ;
}; // class nsSpinnerFrame
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
//
// nsSplitterFrame
//
#ifndef nsSplitterFrame_h__
#define nsSplitterFrame_h__
#include "nsBoxFrame.h"
#include "nsIAnonymousContentCreator.h"
class nsISupportsArray;
class nsSplitterFrameImpl;
nsresult NS_NewSplitterFrame(nsIFrame** aResult) ;
class nsSplitterFrame : public nsBoxFrame, public nsIAnonymousContentCreator
{
public:
nsSplitterFrame();
~nsSplitterFrame();
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsString& aResult) const {
return MakeFrameName("SplitterFrame", aResult);
}
#endif
// nsIFrame overrides
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD GetCursor(nsIPresContext& aPresContext,
nsPoint& aPoint,
PRInt32& aCursor);
// nsIAnonymousContentCreator
NS_IMETHOD CreateAnonymousContent(nsISupportsArray& aAnonymousItems);
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; }
NS_IMETHOD_(nsrefcnt) Release(void) { return NS_OK; }
NS_IMETHOD HandlePress(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleMultiplePress(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleDrag(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleRelease(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, nsIFrame** aFrame);
private:
friend class nsSplitterFrameImpl;
nsSplitterFrameImpl* mImpl;
// XXX Hack
nsIPresContext* mPresContext; // weak reference
}; // class nsSplitterFrame
#endif

View File

@@ -0,0 +1,256 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsStdColorPicker.h"
#include "nsColor.h"
#include "nsCRT.h"
#include "nsXULAtoms.h"
#include "nsIDOMElement.h"
#include "nsIContent.h"
#include "prtypes.h"
#include "nsIAtom.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsCSSRendering.h"
#include "nsINameSpaceManager.h"
static char *NosePalette[] = {
"#00FF00","#00ED00","#00DB00","#00C900","#00B700","#00A500","#009300","#008100","#006F00","#005D00",
"#FFFF00","#EDED00","#DBDB00","#C9C900","#B7B700","#A5A500","#939300","#818100","#6F6F00","#5D5D00",
"#FFFF00","#F5ED00","#EBDB00","#E1C900","#D7B700","#CDA500","#C39300","#B98100","#AF6F00","#A55D00"
};
static char* StandardPalette[] = {
"#FFFFFF","#FFCCCC","#FFCC99","#FFFF99","#FFFFCC","#99FF99","#99FFFF","#CCFFFF","#CCCCFF","#FFCCFF",
"#CCCCCC","#FF6666","#FFCC33","#FFFF66","#FFFF99","#66FF99","#33FFFF","#66FFFF","#9999FF","#FF99FF",
"#C0C0C0","#FF0000","#FF9900","#FFCC66","#FFFF00","#33FF33","#66CCCC","#33CCFF","#6666CC","#CC66CC",
"#999999","#CC0000","#FF6600","#FFCC33","#FFCC00","#33CC00","#00CCCC","#3366FF","#6633FF","#CC33CC",
"#666666","#990000","#CC6600","#CC9933","#999900","#009900","#339999","#3333FF","#6600CC","#993399",
"#333333","#660000","#993300","#996633","#666600","#006600","#336666","#000099","#333399","#663366",
"#000000","#330000","#663300","#663333","#333300","#003300","#003333","#000066","#330099","#330033"
};
static char *WebPalette[] = {
"#FFFFFF", "#FFFFCC", "#FFFF99", "#FFFF66", "#FFFF33", "#FFFF00", "#FFCCFF", "#FFCCCC",
"#FFCC99", "#FFCC66", "#FFCC33", "#FFCC00", "#FF99FF", "#FF99CC", "#FF9999", "#FF9966",
"#FF9933", "#FF9900", "#FF66FF", "#FF66CC", "#FF6699", "#FF6666", "#FF6633", "#FF6600",
"#FF33FF", "#FF33CC", "#FF3399", "#FF3366", "#FF3333", "#FF3300", "#FF00FF", "#FF00CC",
"#FF0099", "#FF0066", "#FF0033", "#FF0000", "#CCFFFF", "#CCFFCC", "#CCFF99", "#CCFF66",
"#CCFF33", "#CCFF00", "#CCCCFF", "#CCCCCC", "#CCCC99", "#CCCC66", "#CCCC33", "#CCCC00",
"#CC99FF", "#CC99CC", "#CC9999", "#CC9966", "#CC9933", "#CC9900", "#CC66FF", "#CC66CC",
"#CC6699", "#CC6666", "#CC6633", "#CC6600", "#CC33FF", "#CC33CC", "#CC3399", "#CC3366",
"#CC3333", "#CC3300", "#CC00FF", "#CC00CC", "#CC0099", "#CC0066", "#CC0033", "#CC0000",
"#99FFFF", "#99FFCC", "#99FF99", "#99FF66", "#99FF33", "#99FF00", "#99CCFF", "#99CCCC",
"#99CC99", "#99CC66", "#99CC33", "#99CC00", "#9999FF", "#9999CC", "#999999", "#999966",
"#999933", "#999900", "#9966FF", "#9966CC", "#996699", "#996666", "#996633", "#996600",
"#9933FF", "#9933CC", "#993399", "#993366", "#993333", "#993300", "#9900FF", "#9900CC",
"#990099", "#990066", "#990033", "#990000", "#66FFFF", "#66FFCC", "#66FF99", "#66FF66",
"#66FF33", "#66FF00", "#66CCFF", "#66CCCC", "#66CC99", "#66CC66", "#66CC33", "#66CC00",
"#6699FF", "#6699CC", "#669999", "#669966", "#669933", "#669900", "#6666FF", "#6666CC",
"#666699", "#666666", "#666633", "#666600", "#6633FF", "#6633CC", "#663399", "#663366",
"#663333", "#663300", "#6600FF", "#6600CC", "#660099", "#660066", "#660033", "#660000",
"#33FFFF", "#33FFCC", "#33FF99", "#33FF66", "#33FF33", "#33FF00", "#33CCFF", "#33CCCC",
"#33CC99", "#33CC66", "#33CC33", "#33CC00", "#3399FF", "#3399CC", "#339999", "#339966",
"#339933", "#339900", "#3366FF", "#3366CC", "#336699", "#336666", "#336633", "#336600",
"#3333FF", "#3333CC", "#333399", "#333366", "#333333", "#333300", "#3300FF", "#3300CC",
"#330099", "#330066", "#330033", "#330000", "#00FFFF", "#00FFCC", "#00FF99", "#00FF66",
"#00FF33", "#00FF00", "#00CCFF", "#00CCCC", "#00CC99", "#00CC66", "#00CC33", "#00CC00",
"#0099FF", "#0099CC", "#009999", "#009966", "#009933", "#009900", "#0066FF", "#0066CC",
"#006699", "#006666", "#006633", "#006600", "#0033FF", "#0033CC", "#003399", "#003366",
"#003333", "#003300", "#0000FF", "#0000CC", "#000099", "#000066", "#000033", "#000000"
};
static char *GrayPalette[] = {
"#000000", "#010101", "#020202", "#030303", "#040404", "#050505", "#060606", "#070707",
"#080808", "#090909", "#0A0A0A", "#0B0B0B", "#0C0C0C", "#0D0D0D", "#0E0E0E", "#0F0F0F",
"#101010", "#111111", "#121212", "#131313", "#141414", "#151515", "#161616", "#171717",
"#181818", "#191919", "#1A1A1A", "#1B1B1B", "#1C1C1C", "#1D1D1D", "#1E1E1E", "#1F1F1F",
"#202020", "#212121", "#222222", "#232323", "#242424", "#252525", "#262626", "#272727",
"#282828", "#292929", "#2A2A2A", "#2B2B2B", "#2C2C2C", "#2D2D2D", "#2E2E2E", "#2F2F2F",
"#303030", "#313131", "#323232", "#333333", "#343434", "#353535", "#363636", "#373737",
"#383838", "#393939", "#3A3A3A", "#3B3B3B", "#3C3C3C", "#3D3D3D", "#3E3E3E", "#3F3F3F",
"#404040", "#414141", "#424242", "#434343", "#444444", "#454545", "#464646", "#474747",
"#484848", "#494949", "#4A4A4A", "#4B4B4B", "#4C4C4C", "#4D4D4D", "#4E3E3E", "#4F4F4F",
"#505050", "#515151", "#525252", "#534343", "#545454", "#555555", "#565656", "#575757",
"#585858", "#595959", "#5A5A5A", "#5B5B5B", "#5C5C5C", "#5D5D5D", "#5E5E5E", "#5F5F5F",
"#606060", "#616161", "#626262", "#636363", "#646464", "#656565", "#666666", "#676767",
"#686868", "#696969", "#6A6A6A", "#6B6B6B", "#6C6C6C", "#6D6D6D", "#6E6E6E", "#6F6F6F",
"#707070", "#717171", "#727272", "#737373", "#747474", "#757575", "#767676", "#777777",
"#787878", "#797979", "#7A7A7A", "#7B7B7B", "#7C7C7C", "#7D7D7D", "#7E7E7E", "#7F7F7F",
"#808080", "#818181", "#828282", "#838383", "#848484", "#858585", "#868686", "#878787",
"#888888", "#898989", "#8A8A8A", "#8B8B8B", "#8C8C8C", "#8D8D8D", "#8E8E8E", "#8F8F8F",
"#909090", "#919191", "#929292", "#939393", "#949494", "#959595", "#969696", "#979797",
"#989898", "#999999", "#9A9A9A", "#9B9B9B", "#9C9C9C", "#9D9D9D", "#9E9E9E", "#9F9F9F",
"#A0A0A0", "#A1A1A1", "#A2A2A2", "#A3A3A3", "#A4A4A4", "#A5A5A5", "#A6A6A6", "#A7A7A7",
"#A8A8A8", "#A9A9A9", "#AAAAAA", "#ABABAB", "#ACACAC", "#ADADAD", "#AEAEAE", "#AFAFAF",
"#B0B0B0", "#B1B1B1", "#B2B2B2", "#B3B3B3", "#B4B4B4", "#B5B5B5", "#B6B6B6", "#B7B7B7",
"#B8B8B8", "#B9B9B9", "#BABABA", "#BBBBBB", "#BCBCBC", "#BDBDBD", "#BEBEBE", "#BFBFBF",
"#C0C0C0", "#C1C1C1", "#C2C2C2", "#C3C3C3", "#C4C4C4", "#C5C5C5", "#C6C6C6", "#C7C7C7",
"#C8C8C8", "#C9C9C9", "#CACACA", "#CBCBCB", "#CCCCCC", "#CDCDCD", "#CECECE", "#CFCFCF",
"#D0D0D0", "#D1D1D1", "#D2D2D2", "#D3D3D3", "#D4D4D4", "#D5D5D5", "#D6D6D6", "#D7D7D7",
"#D8D8D8", "#D9D9D9", "#DADADA", "#DBDBDB", "#DCDCDC", "#DDDDDD", "#DEDEDE", "#DFDFDF",
"#E0E0E0", "#E1E1E1", "#E2E2E2", "#E3E3E3", "#E4E4E4", "#E5E5E5", "#E6E6E6", "#E7E7E7",
"#E8E8E8", "#E9E9E9", "#EAEAEA", "#EBEBEB", "#ECECEC", "#EDEDED", "#EEEEEE", "#EFEFEF",
"#F0F0F0", "#F1F1F1", "#F2F2F2", "#F3F3F3", "#F4F4F4", "#F5F5F5", "#F6F6F6", "#F7F7F7",
"#F8F8F8", "#F9F9F9", "#FAFAFA", "#FBFBFB", "#FCFCFC", "#FDFDFD", "#FEFEFE", "#FFFFFF"
};
NS_IMPL_ISUPPORTS1(nsStdColorPicker, nsIColorPicker)
nsStdColorPicker::nsStdColorPicker()
{
mColors = 0;
mNumCols = 0;
mNumRows = 0;
mFrameWidth = 0;
mFrameHeight = 0;
mBlockWidth = 20;
mBlockHeight = 20;
}
nsStdColorPicker::~nsStdColorPicker()
{
}
NS_IMETHODIMP nsStdColorPicker::Init(nsIContent *aContent)
{
nsAutoString palette;
aContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::palettename, palette);
if (palette.EqualsIgnoreCase("web"))
{
printf("web picked\n");
mPalette = WebPalette;
mNumCols = 12;
mColors = sizeof(WebPalette) / sizeof(char *);
}
else if (palette.EqualsIgnoreCase("nose"))
{
printf("nose picked\n");
mPalette = NosePalette;
mNumCols = 10;
mColors = sizeof(NosePalette) / sizeof(char *);
}
else if (palette.EqualsIgnoreCase("gray") || palette.EqualsIgnoreCase("grey"))
{
printf("gray picked\n");
mPalette = GrayPalette;
mNumCols = 10;
mColors = sizeof(GrayPalette) / sizeof(char *);
}
else
{
printf("standard picked\n");
mPalette = StandardPalette;
mNumCols = 10;
mColors = sizeof(StandardPalette) / sizeof(char *);
}
mNumRows = NSToIntCeil(nscoord(mColors/mNumCols)) - 1;
return NS_OK;
}
NS_IMETHODIMP nsStdColorPicker::Paint(nsIPresContext * aPresContext, nsIRenderingContext * aRenderingContext)
{
int i = 0;
int row = 0;
int col = 0;
nscolor color = 0;
float p2t;
PRInt32 width, height;
aPresContext->GetScaledPixelsToTwips(&p2t);
width = NSToIntRound(mBlockWidth * p2t);
height = NSToIntRound(mBlockHeight * p2t);
// aRenderingContext->SetColor(0);
// aRenderingContext->FillRect(0, 0, (mNumCols)*width, mNumRows*height);
for (i=0;i<mColors;i++)
{
NS_LooseHexToRGB(mPalette[i], &color);
aRenderingContext->SetColor(color);
aRenderingContext->FillRect(col*width, row*height, width, height);
if (col+1 == mNumCols)
{
col = 0;
row++;
}
else
col++;
}
return NS_OK;
}
NS_IMETHODIMP nsStdColorPicker::GetColor(PRInt32 aX, PRInt32 aY, char **aColor)
{
int cur_col = aX / mBlockWidth;
int cur_row = aY / mBlockHeight;
int f = mNumCols * cur_row + cur_col;
if (f >= mColors)
{
return NS_ERROR_FAILURE;
}
*aColor = nsCRT::strdup(mPalette[f]);
return NS_OK;
}
NS_IMETHODIMP nsStdColorPicker::SetSize(PRInt32 aWidth, PRInt32 aHeight)
{
mFrameWidth = aWidth;
mFrameHeight = aHeight;
if (aWidth != -1)
mBlockWidth = NSToIntRound(nscoord(aWidth / mNumCols));
if (aWidth != -1)
mBlockHeight = NSToIntRound(nscoord(aHeight / mNumRows));
mFrameWidth = NSToIntRound(nscoord((mNumCols) * mBlockWidth));
mFrameHeight = NSToIntRound(nscoord((mNumRows) * mBlockHeight));
return NS_OK;
}
NS_IMETHODIMP nsStdColorPicker::GetSize(PRInt32 *aWidth, PRInt32 *aHeight)
{
*aWidth = mFrameWidth;
*aHeight = mFrameHeight;
return NS_OK;
}

View File

@@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef __nsStdColorPicker_h__
#define __nsStdColorPicker_h__
#include "nsISupports.h"
#include "nsrootidl.h"
#include "nsIPresContext.h"
#include "nsIRenderingContext.h"
#include "nsIColorPicker.h"
class nsStdColorPicker : public nsIColorPicker {
public:
nsStdColorPicker();
virtual ~nsStdColorPicker();
NS_DECL_ISUPPORTS
NS_DECL_NSICOLORPICKER
private:
char **mPalette;
PRInt32 mColors;
PRInt32 mNumCols;
PRInt32 mNumRows;
PRInt32 mBlockWidth;
PRInt32 mBlockHeight;
PRInt32 mFrameWidth;
PRInt32 mFrameHeight;
};
#endif /* __nsStdColorPicker_h__ */

View File

@@ -0,0 +1,173 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Eric Vaughan
// Netscape Communications
//
// See documentation in associated header file
//
#include "nsTabFrame.h"
#include "nsIStyleContext.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
#include "nsCOMPtr.h"
#include "nsHTMLIIDs.h"
#include "nsUnitConversion.h"
#include "nsINameSpaceManager.h"
#include "nsHTMLAtoms.h"
#include "nsXULAtoms.h"
#include "nsIReflowCommand.h"
#include <stdio.h>
//
// NS_NewToolbarFrame
//
// Creates a new Toolbar frame and returns it in |aNewFrame|
//
nsresult
NS_NewTabFrame ( nsIFrame** aNewFrame )
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsTabFrame* it = new nsTabFrame;
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
} // NS_NewTabFrame
void
nsTabFrame::MouseClicked(nsIPresContext* aPresContext)
{
// get our index
PRInt32 index = 0;
GetIndexInParent(mContent, index);
// get the tab control
nsIContent* tabcontrol = nsnull;
GetTabControl(mContent, tabcontrol);
// get the tab panel
nsIContent* tabpanel = nsnull;
GetChildWithTag(nsXULAtoms::tabpanel, tabcontrol, tabpanel);
if (!tabpanel) {
return;
}
// unselect the old tab
// get the current index
nsAutoString v;
PRInt32 error;
tabpanel->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::index, v);
PRInt32 oldIndex = v.ToInteger(&error);
if (oldIndex != index)
{
// get the tab box
nsIContent* parent;
mContent->GetParent(parent);
// get child
nsIContent* child;
parent->ChildAt(oldIndex, child);
// set the old tab to be unselected
child->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::selected, "false", PR_TRUE);
// set the new tab to be selected
mContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::selected, "true", PR_TRUE);
}
// set the panels index
char value[100];
sprintf(value, "%d", index);
tabpanel->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::index, value, PR_TRUE);
}
nsresult
nsTabFrame::GetChildWithTag(nsIAtom* atom, nsIContent* start, nsIContent*& tabpanel)
{
// recursively search our children
PRInt32 count = 0;
start->ChildCount(count);
for (PRInt32 i = 0; i < count; i++)
{
nsIContent* child = nsnull;
start->ChildAt(i,child);
// see if it is the child
nsCOMPtr<nsIAtom> tag;
child->GetTag(*getter_AddRefs(tag));
if (tag.get() == atom)
{
tabpanel = child;
return NS_OK;
}
// recursive search the child
nsIContent* found = nsnull;
GetChildWithTag(atom, child, found);
if (found != nsnull) {
tabpanel = found;
return NS_OK;
}
}
tabpanel = nsnull;
return NS_OK;
}
nsresult
nsTabFrame::GetTabControl(nsIContent* content, nsIContent*& tabcontrol)
{
while(nsnull != content)
{
content->GetParent(content);
if (content) {
nsCOMPtr<nsIAtom> atom;
if (content->GetTag(*getter_AddRefs(atom)) == NS_OK && atom.get() == nsXULAtoms::tabcontrol) {
tabcontrol = content;
return NS_OK;
}
}
}
tabcontrol = nsnull;
return NS_OK;
}
nsresult
nsTabFrame::GetIndexInParent(nsIContent* content, PRInt32& index)
{
nsIContent* parent;
content->GetParent(parent);
return parent->IndexOf(content, index);
}

View File

@@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
/**
Eric D Vaughan
This class lays out its children either vertically or horizontally
**/
#ifndef nsTabFrame_h___
#define nsTabFrame_h___
#include "nsHTMLButtonControlFrame.h"
class nsTabControlFrame;
class nsTabFrame : public nsHTMLButtonControlFrame
{
public:
friend nsresult NS_NewTabFrame(nsIFrame** aNewFrame);
virtual void MouseClicked(nsIPresContext* aPresContext);
protected:
virtual nsresult GetChildWithTag(nsIAtom* atom, nsIContent* start, nsIContent*& tabpanel);
virtual nsresult GetTabControl(nsIContent* content, nsIContent*& tabcontrol);
virtual nsresult GetIndexInParent(nsIContent* content, PRInt32& index);
// Selection Methods
// XXX Doc me... (in nsIFrame.h puhleeze)
// XXX If these are selection specific, then the name should imply selection
// rather than generic event processing, e.g., SelectionHandlePress...
NS_IMETHOD HandlePress(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus) { return NS_OK; }
NS_IMETHOD HandleMultiplePress(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus) { return NS_OK; }
NS_IMETHOD HandleDrag(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus) { return NS_OK; }
NS_IMETHOD HandleRelease(nsIPresContext& aPresContext,
nsGUIEvent * aEvent,
nsEventStatus& aEventStatus) { return NS_OK; }
private:
nsTabControlFrame* mTabControlFrame;
}; // class nsTabFrame
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsTitledButtonFrame_h___
#define nsTitledButtonFrame_h___
#include "nsHTMLImageLoader.h"
#include "nsLeafFrame.h"
#include "nsIBox.h"
class nsIPopUpMenu;
class nsTitledButtonRenderer;
class nsTitledButtonFrame : public nsLeafFrame, public nsIBox
{
public:
enum CroppingStyle { CropNone, CropLeft, CropRight, CropCenter };
friend nsresult NS_NewTitledButtonFrame(nsIFrame** aNewFrame);
// nsIBox frame interface
NS_IMETHOD GetBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize);
NS_IMETHOD Dirty(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild);
NS_DECL_ISUPPORTS
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* asPrevInFlow);
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint);
NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext** aStyleContext) const;
NS_IMETHOD SetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext* aStyleContext);
NS_IMETHOD DidSetStyleContext (nsIPresContext* aPresContext);
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
NS_IMETHOD GetFrameName(nsString& aResult) const;
virtual void UpdateAttributes(nsIPresContext& aPresContext);
virtual void UpdateImage(nsIPresContext& aPresContext);
// nsIHTMLReflow overrides
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
~nsTitledButtonFrame();
protected:
enum CheckState { eUnset, eOff, eOn, eMixed } ;
CheckState GetCurrentCheckState();
void SetCurrentCheckState(CheckState aState);
void UpdateAccessUnderline();
virtual void MouseClicked(nsIPresContext & aPresContext);
NS_IMETHOD PaintTitle(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD PaintImage(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
virtual void LayoutTitleAndImage(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
virtual void GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize);
void DisplayAltFeedback(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
PRInt32 aIconId);
void DisplayAltText(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsString& aAltText,
const nsRect& aRect);
void MeasureString(const PRUnichar* aString,
PRInt32 aLength,
nscoord aMaxWidth,
PRUint32& aMaxFit,
nsIRenderingContext& aContext);
nsTitledButtonFrame();
virtual void CalculateTitleForWidth(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, nscoord aWidth);
virtual void GetTextSize(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsString& aString, nsSize& aSize);
virtual void SetDisabled(nsAutoString aDisabled);
static nsresult UpdateImageFrame(nsIPresContext* aPresContext,
nsHTMLImageLoader* aLoader,
nsIFrame* aFrame,
void* aClosure,
PRUint32 aStatus);
void GetImageSource(nsString& aResult);
virtual void GetImageSize(nsIPresContext* aPresContext);
private:
// tri state methods
void CheckStateToString ( CheckState inState, nsString& outStateAsString ) ;
CheckState StringToCheckState ( const nsString & aStateAsString ) ;
PRBool mHasOnceBeenInMixedState;
CroppingStyle mCropType;
PRIntn mAlign;
nsString mTitle;
nsString mCroppedTitle;
nsHTMLImageLoader mImageLoader;
PRBool mSizeFrozen;
nsMargin mBorderPadding;
nsRect mImageRect;
nsRect mTitleRect;
PRBool mNeedsLayout;
nscoord mSpacing;
nsTitledButtonRenderer* mRenderer;
PRBool mHasImage;
// accesskey highlighting
PRBool mNeedsAccessUpdate;
PRInt32 mAccesskeyIndex;
nscoord mBeforeWidth, mAccessWidth, mAccessUnderlineSize, mAccessOffset;
// nsIPopUpMenu * mPopUpMenu;
// PRBool mMenuIsPoppedUp;
}; // class nsTitledButtonFrame
#endif /* nsTitledButtonFrame_h___ */

View File

@@ -0,0 +1,457 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsToolbarDragListener.h"
#include "nsToolbarFrame.h"
#include "nsCOMPtr.h"
#include "nsIDOMMouseEvent.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
#include "nsIDOMElement.h"
#include "nsXULAtoms.h"
#include "nsIEventStateManager.h"
#include "nsISupportsPrimitives.h"
#include "nsINameSpaceManager.h"
#include "nsIDOMXULDocument.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
NS_IMPL_ADDREF(nsToolbarDragListener)
NS_IMPL_RELEASE(nsToolbarDragListener)
//
// nsToolbarDragListener ctor
//
// Init member variables. We can't really do much of anything important here because
// any subframes might not be totally intialized yet, or in the hash table
//
nsToolbarDragListener :: nsToolbarDragListener ( nsToolbarFrame* inToolbar, nsIPresContext* inPresContext )
: mToolbar(inToolbar), mPresContext(inPresContext), mCurrentDropLoc(-1)
{
NS_INIT_REFCNT();
// we really need this all over the place. just be safe that we have it.
NS_ASSERTION ( mPresContext, "no pres context set on toolbar drag listener" );
} // nsToolbarDragListener ctor
//
// nsToolbarDragListener dtor
//
// Cleanup.
//
nsToolbarDragListener::~nsToolbarDragListener()
{
}
//
// QueryInterface
//
// Modeled after scc's reference implementation
// http://www.mozilla.org/projects/xpcom/QI.html
//
nsresult
nsToolbarDragListener::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if ( !aInstancePtr)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsCOMTypeInfo<nsIDOMEventListener>::GetIID()))
*aInstancePtr = NS_STATIC_CAST(nsIDOMEventListener*, NS_STATIC_CAST(nsIDOMDragListener*, this));
else if (aIID.Equals(nsCOMTypeInfo<nsIDOMDragListener>::GetIID()))
*aInstancePtr = NS_STATIC_CAST(nsIDOMDragListener*, this);
else if (aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
*aInstancePtr = NS_STATIC_CAST(nsISupports*, NS_STATIC_CAST(nsIDOMDragListener*, this));
else
*aInstancePtr = 0;
nsresult status;
if ( !*aInstancePtr )
status = NS_NOINTERFACE;
else {
NS_ADDREF( NS_REINTERPRET_CAST(nsISupports*, *aInstancePtr) );
status = NS_OK;
}
return status;
}
////////////////////////////////////////////////////////////////////////
nsresult
nsToolbarDragListener::HandleEvent(nsIDOMEvent* aEvent)
{
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
nsresult
nsToolbarDragListener::DragGesture(nsIDOMEvent* aDragEvent)
{
// this code should all be in JS.
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
nsresult
nsToolbarDragListener::DragEnter(nsIDOMEvent* aDragEvent)
{
// We don't need to do anything special here. If anything does need to be done,
// the code should all be in JS.
return NS_OK;
}
//
// ItemMouseIsOver
//
// Figure out which child item mouse is over. |outIndex| is the index of the item the object
// should be dropped _before_. Therefore if the item should be dropped at the end, the index
// will be greater than the number of items in the list. |outOnChild| is true if the item
// is a container and the drop would be "on" that item.
//
void
nsToolbarDragListener :: ItemMouseIsOver ( nsIDOMEvent* aDragEvent, nscoord* outXLoc,
PRUint32* outIndex, PRBool* outOnChild )
{
*outOnChild = PR_FALSE;
// figure out which frame is the right one for determining the drop feedback. Do we
// want to do this every time? We certainly can't do it upon toolbar creation (hash
// tables not setup at that time), so we're forced to do it now. What happens if while
// we're dragging some rule gets fired that causes the frame to go away?
nsIFrame* dropAreaFrame = LocateDropAreaFrame();
if ( !dropAreaFrame ) {
// gaaak, we're doomed.
outIndex = 0;
outXLoc = 0;
return;
}
//
// Get the mouse coordinates from the DOM event, but they will be in the
// window/widget coordinate system. We must first get them into the frame-relative
// coordinate system. Yuck.
//
// get mouse coordinates and translate them into twips
nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aDragEvent));
PRInt32 x,y = 0;
mouseEvent->GetClientX(&x);
mouseEvent->GetClientY(&y);
float p2t;
mPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nscoord xp = NSIntPixelsToTwips(x, p2t);
nscoord yp = NSIntPixelsToTwips(y, p2t);
// compute the offset to top level in twips
PRInt32 frameOffsetX = 0, frameOffsetY = 0;
nsIFrame* curr = dropAreaFrame;
curr->GetParent(&curr);
float t2p;
mPresContext->GetTwipsToPixels(&t2p);
while ( curr ) {
nsPoint origin;
curr->GetOrigin(origin); // in twips
frameOffsetX += origin.x; // build the offset incrementally
frameOffsetY += origin.y;
curr->GetParent(&curr); // moving up the chain
} // until we reach the top
// subtract the offset from the x,y coord to put into frame relative coordinates.
xp -= frameOffsetX;
yp -= frameOffsetY;
nsPoint pnt(xp, yp);
// get the toolbar's rect
nsRect tbRect;
dropAreaFrame->GetRect(tbRect);
PRUint32 count = 0;
PRBool found = PR_FALSE;
nsIFrame* childFrame;
nsRect rect; // child frame's rect
nsRect prevRect(-1, -1, 0, 0);
//
// Now loop through the child and see if the mouse is over a child
//
dropAreaFrame->FirstChild(nsnull, &childFrame);
while ( childFrame ) {
// The mouse coords are in the toolbar's domain
// Get child's rect and adjust to the toolbar's domain
childFrame->GetRect(rect);
rect.MoveBy(tbRect.x, tbRect.y);
// remember the previous child x location
if (pnt.x < rect.x && prevRect.x == -1)
prevRect = rect;
// now check to see if the mouse inside an items bounds
if (rect.Contains(pnt)) {
nsCOMPtr<nsIContent> content;
childFrame->GetContent(getter_AddRefs(content));
if ( content ) {
nsCOMPtr<nsIAtom> tag;
content->GetTag(*getter_AddRefs(tag));
// for now I am checking for both titlebutton and toolbar items
// XXX but the check for titlebutton should be removed in the future
if (tag.get() == nsXULAtoms::titledbutton || tag.get() == nsXULAtoms::toolbaritem) {
// now check if item is a container
PRBool isContainer = PR_FALSE;
nsCOMPtr<nsIDOMElement> domElement ( do_QueryInterface(content) );
if ( domElement ) {
nsAutoString value;
domElement->GetAttribute(nsAutoString("container"), value); // can't use an atom here =(
isContainer = value.Equals("true");
}
else
NS_WARNING("Not a DOM element");
// if we have a container, the area is broken up into 3 pieces (left, middle, right). If
// it isn't it's only broken up into two (left and right)
PRInt32 xc = -1;
if ( isContainer ) {
if (pnt.x <= (rect.x + (rect.width / 4))) {
*outIndex = count;
xc = rect.x - tbRect.x;
}
else if (pnt.x >= (rect.x + PRInt32(float(rect.width) *0.75))) {
*outIndex = count + 1;
xc = rect.x - tbRect.x + rect.width - onePixel;
}
else {
// we're on a container, don't draw anything so xc shouldn't get set.
*outIndex = count;
*outOnChild = PR_TRUE;
}
} else {
if (pnt.x <= (rect.x + (rect.width / 2))) {
*outIndex = count;
xc = rect.x - tbRect.x;
}
else {
*outIndex = count + 1;
xc = rect.x - tbRect.x + rect.width + onePixel;
}
}
*outXLoc = xc;
}
else {
// mouse is over something (probably a spacer) so return the left side of
// the spacer.
*outXLoc = rect.x - tbRect.x;
*outIndex = count;
}
// found something, break out of the loop
found = PR_TRUE;
break;
}
} // if mouse is in an item
nsresult rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(rv == NS_OK,"failed to get next child");
count++;
} // foreach child
if (!found) {
*outIndex = count; // already incremented past last item
if ( count )
*outXLoc = prevRect.x - tbRect.x + rect.width + onePixel;
else
*outXLoc = onePixel;
}
}
//
// DragOver
//
// The mouse has moved over the toolbar while a drag is happening. We really just want to
// "annotate" the toolbar with the current drop location. We don't want to make any judgement
// as this stage as to whether or not the drag should be accepted or draw any feedback.
//
nsresult
nsToolbarDragListener::DragOver(nsIDOMEvent* aDragEvent)
{
#if 0
nsCOMPtr<nsIContent> c;
mToolbar->GetContent ( getter_AddRefs(c) );
nsCOMPtr<nsIDOMNode> d ( do_QueryInterface(c) );
nsCOMPtr<nsIDOMNode> t;
aDragEvent->GetTarget ( getter_AddRefs(t) );
printf ( "DRAGOVER:: toolbar content is %ld, as DOMNode %ld, target is %ld\n", c, d, t );
#endif
// Check to see if the mouse is over an item and which one it is.
nscoord xLoc = 0;
PRBool onChild;
PRUint32 beforeIndex = 0;
ItemMouseIsOver(aDragEvent, &xLoc, &beforeIndex, &onChild);
if ( xLoc != mCurrentDropLoc ) {
// stash the new location in the toolbar's content model. Note that the toolbar code doesn't
// care at all about "tb-droplocation", only the coordinate so there is no need to send the
// AttributeChanged() about that attribute.
nsCOMPtr<nsIContent> content;
mToolbar->GetContent ( getter_AddRefs(content) );
if ( content ) {
char buffer[10];
// need the cast, because on some platforms, PR[U]int32 != long, but we're using "%ld"
sprintf(buffer, "%ld", NS_STATIC_CAST(long, xLoc));
content->SetAttribute ( kNameSpaceID_None, nsXULAtoms::tbDropLocationCoord, buffer, PR_TRUE );
sprintf(buffer, "%ld", NS_STATIC_CAST(long, beforeIndex));
content->SetAttribute ( kNameSpaceID_None, nsXULAtoms::tbDropLocation, "1", PR_FALSE );
content->SetAttribute ( kNameSpaceID_None, nsXULAtoms::tbDropOn, onChild ? "true" : "false", PR_FALSE );
}
// cache the current drop location
mCurrentDropLoc = xLoc;
}
// NS_OK means event is NOT consumed. We want to make sure JS gets this so it
// can determine if the drag is allowed.
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
nsresult
nsToolbarDragListener::DragExit(nsIDOMEvent* aDragEvent)
{
// there are some bugs that cause us to not be able to correctly track dragExit events
// so until then we just get on our knees and pray we don't get fooled again.
#if 0
nsCOMPtr<nsIContent> c;
mToolbar->GetContent ( getter_AddRefs(c) );
nsCOMPtr<nsIDOMNode> d ( do_QueryInterface(c) );
nsCOMPtr<nsIDOMNode> t;
aDragEvent->GetTarget ( getter_AddRefs(t) );
printf ( "DRAGEXIT:: toolbar DOMNode %ld, target is %ld\n", d, t );
nsCOMPtr<nsIContent> content;
mToolbar->GetContent ( getter_AddRefs(content) );
// we will get a drag exit event on sub items because we catch the event on the way down. If
// the target is not our toolbar, then ignore it.
nsCOMPtr<nsIDOMNode> toolbarDOMNode ( do_QueryInterface(content) );
nsCOMPtr<nsIDOMNode> eventTarget;
aDragEvent->GetTarget ( getter_AddRefs(eventTarget) );
if ( eventTarget != toolbarDOMNode )
return NS_OK;
printf("***REAL EXIT EVENT\n");
// tell the toolbar to not do any more drop feedback. Note that the toolbar code doesn't
// care at all about "tb-droplocation", only the coordinate so there is no need to send the
// AttributeChanged() about that attribute.
char buffer[10];
sprintf(buffer, "%ld", -1);
content->SetAttribute ( kNameSpaceID_None, nsXULAtoms::tbDropLocationCoord, buffer, PR_TRUE );
content->SetAttribute ( kNameSpaceID_None, nsXULAtoms::tbDropLocation, buffer, PR_FALSE );
// cache the current drop location
mCurrentDropLoc = -1;
#endif
return NS_OK; // don't consume event
}
////////////////////////////////////////////////////////////////////////
nsresult
nsToolbarDragListener::DragDrop(nsIDOMEvent* aMouseEvent)
{
// this code should all be in JS.
return NS_OK;
}
//
// LocateDropAreaFrame
//
// Returns the frame (or subframe) that contains the buttons that can be dragged.
// Either it will be the toolbar frame as a whole, or it will be some subframe of the bar id'd by
// the |dragdroparea| attribute.
//
nsIFrame*
nsToolbarDragListener :: LocateDropAreaFrame ( )
{
nsIFrame* retVal = nsnull;
// is a subframe the drag/drop area? determine if the attribute is set.
nsString dropAreaID;
PRBool dropAreaIsSubframe = PR_FALSE;
nsCOMPtr<nsIContent> toolbarContent;
mToolbar->GetContent ( getter_AddRefs(toolbarContent) );
if ( toolbarContent ) {
if ( toolbarContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::tbDragDropArea, dropAreaID) == NS_CONTENT_ATTR_HAS_VALUE )
dropAreaIsSubframe = PR_TRUE;
}
// if there is a named subframe, go find it, otherwise use the entire toolbar
if ( dropAreaIsSubframe ) {
// get the presShell so we can call GetPrimaryFrameFor later.
nsCOMPtr<nsIPresShell> presShell;
mPresContext->GetShell ( getter_AddRefs(presShell) );
// get the document so we can get do a GetElementByID.
nsCOMPtr<nsIDocument> document;
toolbarContent->GetDocument ( *getter_AddRefs(document) );
if ( document ) {
nsCOMPtr<nsIDOMXULDocument> xulDoc ( do_QueryInterface(document) );
if ( xulDoc ) {
nsCOMPtr<nsIDOMElement> domElementOfSubframe;
xulDoc->GetElementById ( dropAreaID, getter_AddRefs(domElementOfSubframe) );
// finally get the frame associated with that dom node
nsCOMPtr<nsIContent> contentOfSubframe ( do_QueryInterface(domElementOfSubframe) );
if ( contentOfSubframe && presShell )
presShell->GetPrimaryFrameFor ( contentOfSubframe, &retVal );
}
}
} // if named subframe
else
retVal = mToolbar;
NS_ASSERTION ( retVal, "toolbar drag listener couldn't figure out the drag area." );
return retVal;
} // LocateDropAreaFrame

View File

@@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsToolbarDragListener_h__
#define nsToolbarDragListener_h__
#include "nsIDOMDragListener.h"
#include "nsCoord.h"
class nsToolbarFrame;
class nsIPresContext;
class nsIDOMEvent;
class nsIFrame;
class nsToolbarDragListener : public nsIDOMDragListener
{
public:
// default ctor and dtor
nsToolbarDragListener ( nsToolbarFrame* inToolbar, nsIPresContext* inPresContext );
virtual ~nsToolbarDragListener();
// interfaces for addref and release and queryinterface
NS_DECL_ISUPPORTS
// nsIDOMDragListener
virtual nsresult HandleEvent(nsIDOMEvent* aEvent);
virtual nsresult DragEnter(nsIDOMEvent* aDragEvent);
virtual nsresult DragOver(nsIDOMEvent* aDragEvent);
virtual nsresult DragExit(nsIDOMEvent* aDragEvent);
virtual nsresult DragDrop(nsIDOMEvent* aDragEvent);
virtual nsresult DragGesture(nsIDOMEvent* aDragEvent);
protected:
// Figure out which child item mouse is over. |outIndex| is the index of the item the object
// should be dropped _before_. Therefore if the item should be dropped at the end, the index
// will be greater than the number of items in the list. |outOnChild| is true if the item
// is a container and the drop would be "on" that item.
void ItemMouseIsOver(nsIDOMEvent* aDragEvent, nscoord* outXLoc, PRUint32* outIndex, PRBool* outOnChild);
// Find the frame (or subframe) that contains the buttons that can be dragged.
nsIFrame* LocateDropAreaFrame ( ) ;
nsToolbarFrame * mToolbar; // toolbar owns me, don't be circular
nsIPresContext * mPresContext; // weak reference
PRInt32 mCurrentDropLoc;
}; // class nsToolbarDragListener
#endif

View File

@@ -0,0 +1,449 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Mike Pinkerton
// Netscape Communications
//
// See documentation in associated header file
//
#include "nsToolbarFrame.h"
#include "nsCSSRendering.h"
#include "nsToolbarDragListener.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMDragListener.h"
#include "nsIContent.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsIViewManager.h"
#include "nsXULAtoms.h"
#include "nsINameSpaceManager.h"
#define TEMP_HACK_FOR_BUG_11291 1
#if TEMP_HACK_FOR_BUG_11291
// for temp fix of bug 11291. This should really be in JavaScript, I think.
#include "nsIDOMNodeList.h"
#include "nsIDOMElement.h"
class nsTEMPDragGestureEater : public nsIDOMDragListener
{
public:
// default ctor and dtor
nsTEMPDragGestureEater ( ) ;
virtual ~nsTEMPDragGestureEater() { };
// interfaces for addref and release and queryinterface
NS_DECL_ISUPPORTS
// nsIDOMMouseListener
virtual nsresult HandleEvent(nsIDOMEvent* aEvent);
virtual nsresult DragEnter(nsIDOMEvent* aMouseEvent);
virtual nsresult DragOver(nsIDOMEvent* aMouseEvent);
virtual nsresult DragExit(nsIDOMEvent* aMouseEvent);
virtual nsresult DragDrop(nsIDOMEvent* aMouseEvent);
virtual nsresult DragGesture(nsIDOMEvent* aMouseEvent);
}; // class nsTEMPDragGestureEater
NS_IMPL_ADDREF(nsTEMPDragGestureEater)
NS_IMPL_RELEASE(nsTEMPDragGestureEater)
nsTEMPDragGestureEater :: nsTEMPDragGestureEater ( )
{
NS_INIT_REFCNT();
}
//
// QueryInterface
//
// Modeled after scc's reference implementation
// http://www.mozilla.org/projects/xpcom/QI.html
//
nsresult
nsTEMPDragGestureEater::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if ( !aInstancePtr)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsCOMTypeInfo<nsIDOMEventListener>::GetIID()))
*aInstancePtr = NS_STATIC_CAST(nsIDOMEventListener*, this);
else if (aIID.Equals(nsCOMTypeInfo<nsIDOMDragListener>::GetIID()))
*aInstancePtr = NS_STATIC_CAST(nsIDOMDragListener*, this);
else if (aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
*aInstancePtr = NS_STATIC_CAST(nsISupports*, NS_STATIC_CAST(nsIDOMDragListener*, this));
else
*aInstancePtr = 0;
nsresult status;
if ( !*aInstancePtr )
status = NS_NOINTERFACE;
else {
NS_ADDREF( NS_REINTERPRET_CAST(nsISupports*, *aInstancePtr) );
status = NS_OK;
}
return status;
}
nsresult
nsTEMPDragGestureEater :: HandleEvent(nsIDOMEvent* aEvent)
{
return NS_OK;
}
nsresult
nsTEMPDragGestureEater::DragGesture(nsIDOMEvent* aMouseEvent)
{
// we want the text widget to see this event, but not anyone above us that
// might be registered as a listener for drags. Therefore, don't
// allow this event to bubble.
aMouseEvent->PreventBubble();
return NS_ERROR_BASE; // means I AM consuming event
}
nsresult
nsTEMPDragGestureEater::DragEnter(nsIDOMEvent* aMouseEvent)
{
return NS_OK; // means I am NOT consuming event
}
nsresult
nsTEMPDragGestureEater::DragOver(nsIDOMEvent* aMouseEvent)
{
return NS_OK; // means I am NOT consuming event
}
nsresult
nsTEMPDragGestureEater::DragExit(nsIDOMEvent* aMouseEvent)
{
return NS_OK; // means I am NOT consuming event
}
nsresult
nsTEMPDragGestureEater::DragDrop(nsIDOMEvent* aMouseEvent)
{
return NS_OK; // means I am NOT consuming event
}
#endif /* TEMP_HACK_FOR_BUG_11291 */
#ifdef XP_MAC
#pragma mark -
#endif
//
// NS_NewToolbarFrame
//
// Creates a new Toolbar frame and returns it in |aNewFrame|
//
nsresult
NS_NewToolbarFrame ( nsIFrame** aNewFrame )
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsToolbarFrame* it = new nsToolbarFrame;
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
// it->SetFlags(aFlags);
* aNewFrame = it;
return NS_OK;
} // NS_NewToolbarFrame
//
// nsToolbarFrame ctor
//
// Most of the work need to be delayed until Init(). Lame!
//
nsToolbarFrame :: nsToolbarFrame ( )
: mXDropLoc ( -1 )
{
}
//
// nsToolbarFrame dtor
//
// Cleanup. Remove our registered event listener from the content model.
//
nsToolbarFrame :: ~nsToolbarFrame ( )
{
nsCOMPtr<nsIContent> content;
GetContent(getter_AddRefs(content));
nsCOMPtr<nsIDOMEventReceiver> reciever(do_QueryInterface(content));
// NOTE: the Remove will delete the drag listener
reciever->RemoveEventListenerByIID((nsIDOMDragListener *)mDragListener, nsIDOMDragListener::GetIID());
}
//
// Init
//
// Setup event listeners for drag and drop. Our frame's lifetime is bounded by the
// lifetime of the content model, so we're guaranteed that the content node won't go away on us. As
// a result, our drag listener can't go away before the frame is deleted. Since the content
// node holds owning references to our drag listener, which we tear down in the dtor, there is no
// need to hold an owning ref to it ourselves.
//
NS_IMETHODIMP
nsToolbarFrame::Init ( nsIPresContext& aPresContext, nsIContent* aContent,
nsIFrame* aParent, nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
nsCOMPtr<nsIContent> content;
GetContent(getter_AddRefs(content));
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(content));
// register our drag over and exit capturers. These annotate the content object
// with enough info to determine where the drop would happen so that JS can
// do the right thing.
mDragListener = new nsToolbarDragListener(this, &aPresContext);
receiver->AddEventListener("dragover", mDragListener, PR_TRUE);
receiver->AddEventListener("dragexit", mDragListener, PR_TRUE);
#if 0 //TEMP_HACK_FOR_BUG_11291
// Ok, this is a hack until Ender lands. We need to have a mouse listener on text widgets
// in order to make sure that mouseDowns within the text widget don't bubble up to the toolbar
// listener. This would cause problems where selecting text and moving the mouse outside the text
// widget and into the toolbar would start a drag (bug #11291)
nsCOMPtr<nsIDOMElement> element ( do_QueryInterface(content) );
if ( element ) {
nsCOMPtr<nsIDOMNodeList> inputList;
element->GetElementsByTagName("INPUT", getter_AddRefs(inputList));
if ( inputList ) {
PRUint32 length = 0;
inputList->GetLength(&length);
for ( PRUint32 i = 0; i < length; ++i ) {
nsCOMPtr<nsIDOMNode> node;
inputList->Item(i, getter_AddRefs(node));
receiver = do_QueryInterface(node);
if ( receiver )
receiver->AddEventListenerByIID(new nsTEMPDragGestureEater, nsIDOMDragListener::GetIID());
// yes, i know this will leak. That's ok, i don't care because this code will go away
}
}
}
#endif
return rv;
}
//
// Paint
//
// Paint our background and border like normal frames, but before we draw the
// children, draw our grippies for each toolbar.
//
NS_IMETHODIMP
nsToolbarFrame :: Paint ( nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
nsresult res = nsBoxFrame::Paint ( aPresContext, aRenderingContext, aDirtyRect, aWhichLayer );
if (mXDropLoc != -1) {
// XXX this is temporary
if (!mMarkerStyle) {
nsCOMPtr<nsIAtom> atom ( getter_AddRefs(NS_NewAtom(":-moz-drop-marker")) );
aPresContext.ProbePseudoStyleContextFor(mContent, atom, mStyleContext,
PR_FALSE, getter_AddRefs(mMarkerStyle));
}
nscolor color;
if (mMarkerStyle) {
const nsStyleColor* styleColor = (const nsStyleColor*)mMarkerStyle->GetStyleData(eStyleStruct_Color);
color = styleColor->mColor;
} else {
color = NS_RGB(0,0,0);
}
// draw different drop feedback depending on if we have subitems or not
int numChildren = 0;
mContent->ChildCount(numChildren);
if ( numChildren ) {
aRenderingContext.SetColor(color);
nsRect dividingLine ( mXDropLoc, 0, 40, mRect.height );
aRenderingContext.FillRect(dividingLine);
}
else
aRenderingContext.DrawRect ( mRect );
}
return res;
} // Paint
//
// GetFrameForPoint
//
// Override to process events in our own frame
//
NS_IMETHODIMP
nsToolbarFrame :: GetFrameForPoint ( nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame)
{
nsresult retVal = nsHTMLContainerFrame::GetFrameForPoint(aPresContext, aPoint, aFrame);
// returning NS_OK means that we tell the frame finding code that we have something
// and to stop looking elsewhere for a frame.
if ( aFrame && *aFrame == this )
retVal = NS_OK;
else if ( retVal != NS_OK ) {
*aFrame = this;
retVal = NS_OK;
}
return retVal;
} // GetFrameForPoint
//
// HandleEvent
//
// Process events that come to this frame. If they end up here, they are
// almost certainly drag and drop events.
//
NS_IMETHODIMP
nsToolbarFrame :: HandleEvent ( nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
if ( !aEvent )
return nsEventStatus_eIgnore;
switch (aEvent->message) {
case NS_DRAGDROP_ENTER:
if (!mMarkerStyle) {
nsCOMPtr<nsIAtom> atom ( getter_AddRefs(NS_NewAtom(":-moz-drop-marker")) );
aPresContext.ProbePseudoStyleContextFor(mContent, atom, mStyleContext,
PR_FALSE,
getter_AddRefs(mMarkerStyle));
}
break;
}
//XXX this needs to change when I am really handling the D&D events
return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
} // HandleEvent
#if NOT_YET_NEEDED
/**
* Call this when styles change
*/
void
nsToolbarFrame::ReResolveStyles(nsIPresContext& aPresContext,
PRInt32 aParentChange,
nsStyleChangeList* aChangeList,
PRInt32* aLocalChange)
{
// style that draw an Marker around the button
// see if the Marker has changed.
/*nsCOMPtr<nsIStyleContext> oldMarker = mMarkerStyle;
nsCOMPtr<nsIAtom> atom ( getter_AddRefs(NS_NewAtom(":-moz-marker")) );
aPresContext.ProbePseudoStyleContextFor(mContent, atom, mStyleContext,
PR_FALSE,
getter_AddRefs(mMarkerStyle));
if ((mMarkerStyle && oldMarker) && (mMarkerStyle != oldMarker)) {
nsFrame::CaptureStyleChangeFor(this, oldMarker, mMarkerStyle,
aParentChange, aChangeList, aLocalChange);
}*/
}
#endif
////////////////////////////////////////////////////////////////////////
// This is temporary until the bubling of event for CSS actions work
////////////////////////////////////////////////////////////////////////
static void ForceDrawFrame(nsIPresContext* aPresContext, nsIFrame * aFrame);
static void ForceDrawFrame(nsIPresContext* aPresContext, nsIFrame * aFrame)
{
if (aFrame == nsnull) {
return;
}
nsRect rect;
nsIView * view;
nsPoint pnt;
aFrame->GetOffsetFromView(aPresContext, pnt, &view);
aFrame->GetRect(rect);
rect.x = pnt.x;
rect.y = pnt.y;
if (view) {
nsCOMPtr<nsIViewManager> viewMgr;
view->GetViewManager(*getter_AddRefs(viewMgr));
if (viewMgr)
viewMgr->UpdateView(view, rect, NS_VMREFRESH_AUTO_DOUBLE_BUFFER | NS_VMREFRESH_IMMEDIATE);
}
}
//
// AttributeChanged
//
// Track several attributes set by the d&d drop feedback tracking mechanism. The first
// is the "tb-triggerrepaint" attribute so JS can trigger a repaint when it
// needs up update the drop feedback. The second is the x (or y, if bar is vertical)
// coordinate of where the drop feedback bar should be drawn.
//
NS_IMETHODIMP
nsToolbarFrame :: AttributeChanged ( nsIPresContext* aPresContext, nsIContent* aChild,
PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aHint)
{
nsresult rv = NS_OK;
if ( aAttribute == nsXULAtoms::tbTriggerRepaint )
ForceDrawFrame ( aPresContext, this );
else if ( aAttribute == nsXULAtoms::tbDropLocationCoord ) {
nsAutoString attribute;
aChild->GetAttribute ( kNameSpaceID_None, aAttribute, attribute );
char* iHateNSString = attribute.ToNewCString();
mXDropLoc = atoi( iHateNSString );
nsAllocator::Free ( iHateNSString );
}
else
rv = nsBoxFrame::AttributeChanged ( aPresContext, aChild, aNameSpaceID, aAttribute, aHint );
return rv;
} // AttributeChanged

View File

@@ -0,0 +1,119 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Mike Pinkerton
// Netscape Communications
//
// nsToolbarFrame is a layout object that contains items (specified as
// children in the DOM). The layout for toolbars is a little complicated, but
// it basically just lays out its children in as a box. Toolbars themselves
// don't know anything about grippies (as in 4.x) but are associated with them
// through toolboxes. This allows a developer to create a standalone toolbar
// (for inclusion in a webpage), which obviously doesn't need to have a grippy.
//
// As mentioned above, the Toolbar expects its toolbars to be its children in
// the DOM. The exact structure of the children is documented on:
// http://www.mozilla.org/xpfe/DMWSpecNew.html
//
// This implementation of toolbars now uses evaughan's box code for layout
// of its children and to determine its size.
//
#ifndef nsToolbarFrame_h__
#define nsToolbarFrame_h__
#define TOOLBARITEM_MIME "moz/toolbaritem"
#define TOOLBAR_MIME "moz/toolbar"
#include "nsCOMPtr.h"
#include "nsBoxFrame.h"
#include "nsIStyleContext.h"
class nsIContent;
class nsIPresContext;
class nsIFrame;
class nsToolbarDragListener;
class nsToolbarFrame : public nsBoxFrame
{
public:
friend nsresult NS_NewToolbarFrame(nsIFrame** aNewFrame);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* asPrevInFlow);
// nsIHTMLReflow overrides
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
// nsFrame overrides
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint, // Overridden to capture events
nsIFrame** aFrame);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint) ;
#if WTF_IS_THIS
//¥¥¥ not sure at all where this comes from. I asked rods, no reply yet.
virtual void ReResolveStyles(nsIPresContext& aPresContext,
PRInt32 aParentChange,
nsStyleChangeList* aChangeList,
PRInt32* aLocalChange);
#endif
#if 0
void SetDropfeedbackLocation(nscoord aX) { mXDropLoc = aX; }
#endif
protected:
nsToolbarFrame();
virtual ~nsToolbarFrame();
// pass-by-value not allowed for a coordinator because it corresponds 1-to-1
// with an element in the UI.
nsToolbarFrame ( const nsToolbarFrame& aFrame ) ; // DO NOT IMPLEMENT
nsToolbarFrame& operator= ( const nsToolbarFrame& aFrame ) ; // DO NOT IMPLEMENT
// our event handler registered with the content model. See the discussion
// in Init() for why this is a weak ref.
nsToolbarDragListener* mDragListener;
// only used during drag and drop for drop feedback. These are not
// guaranteed to be meaningful when no drop is underway.
PRInt32 mXDropLoc;
nsCOMPtr<nsIStyleContext> mMarkerStyle;
}; // class nsToolbarFrame
#endif

View File

@@ -0,0 +1,172 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsToolbarItemFrame.h"
#include "nsCOMPtr.h"
#include "nsWidgetsCID.h"
// Drag & Drop, Clipboard Support
static NS_DEFINE_CID(kCDragServiceCID, NS_DRAGSERVICE_CID);
static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID);
static NS_DEFINE_IID(kCDataFlavorCID, NS_DATAFLAVOR_CID);
//
// NS_NewToolbarItemFrame (friend)
//
// Creates a new toolbar item frame and returns it in |aNewFrame|
//
nsresult
NS_NewToolbarItemFrame ( nsIFrame** aNewFrame )
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if ( !aNewFrame )
return NS_ERROR_NULL_POINTER;
nsToolbarItemFrame* it = new nsToolbarItemFrame;
if ( !it )
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
} // NS_NewToolbarItemFrame
//
// nsToolbarItemFrame ctor and dtor
//
nsToolbarItemFrame::nsToolbarItemFrame()
{
}
nsToolbarItemFrame::~nsToolbarItemFrame()
{
}
//
// Init
//
// Ummm, just forwards for now.
//
NS_IMETHODIMP
nsToolbarItemFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
return rv;
}
//
// Init
//
// Ummm, just forwards for now. Most of this code is now in the drag listener's
// mouseMoved event.
//
// ¥¥¥ remove all this.
//
NS_IMETHODIMP
nsToolbarItemFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
// if disabled do nothing
/*if (PR_TRUE == mRenderer.isDisabled()) {
return NS_OK;
}
switch (aEvent->message) {
case NS_KEY_PRESS:
if (NS_KEY_EVENT == aEvent->eventStructType) {
nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
if (NS_VK_SPACE == keyEvent->keyCode || NS_VK_RETURN == keyEvent->keyCode) {
MouseClicked(aPresContext);
}
}
break;
case NS_MOUSE_LEFT_CLICK:
MouseClicked(aPresContext);
break;
}
*/
/* // Start Drag
nsIDragService* dragService;
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
nsIDragService::GetIID(),
(nsISupports **)&dragService);
if (NS_OK == rv) {
nsCOMPtr<nsITransferable> trans;
rv = nsComponentManager::CreateInstance(kCTransferableCID, nsnull,
nsITransferable::GetIID(), getter_AddRefs(trans));
nsCOMPtr<nsITransferable> trans2;
rv = nsComponentManager::CreateInstance(kCTransferableCID, nsnull,
nsITransferable::GetIID(), getter_AddRefs(trans2));
if ( trans && trans2 ) {
nsString textPlainFlavor ( "text/plain" );
trans->AddDataFlavor(&textPlainFlavor);
nsString dragText = "Drag Text";
PRUint32 len = 9;
trans->SetTransferData(&textPlainFlavor, dragText.ToNewCString(), len); // transferable consumes the data
trans2->AddDataFlavor(&textPlainFlavor);
nsString dragText2 = "More Drag Text";
len = 14;
trans2->SetTransferData(&textPlainFlavor, dragText2.ToNewCString(), len); // transferable consumes the data
nsCOMPtr<nsISupportsArray> items;
NS_NewISupportsArray(getter_AddRefs(items));
if ( items ) {
items->AppendElement(trans);
items->AppendElement(trans2);
dragService->InvokeDragSession(items, nsnull, nsIDragService::DRAGDROP_ACTION_COPY | nsIDragService::DRAGDROP_ACTION_MOVE);
}
}
nsServiceManager::ReleaseService(kCDragServiceCID, dragService);
} */
printf("ToolbarItem %d\n", aEvent->message);
return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
/*
* We are a frame and we do not maintain a ref count
*/
NS_IMETHODIMP_(nsrefcnt)
nsToolbarItemFrame::AddRef(void)
{
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
nsToolbarItemFrame::Release(void)
{
return NS_OK;
}

View File

@@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsToolbarItemFrame_h___
#define nsToolbarItemFrame_h___
#include "nsBoxFrame.h"
class nsIFrame;
class nsIPresContext;
class nsIStyleContext;
class nsToolbarItemFrame : public nsBoxFrame
{
public:
nsToolbarItemFrame();
~nsToolbarItemFrame();
friend nsresult NS_NewToolbarItemFrame(nsIFrame** aNewFrame);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* asPrevInFlow);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
}; // class nsToolbarItemFrame
#endif /* nsToolbarItemFrame_h___ */

View File

@@ -0,0 +1,932 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Mike Pinkerton
// Netscape Communications
//
// Significant portions of the collapse/expanding code donated by Chris Lattner
// (sabre@skylab.org). Thanks Chris!
//
// See documentation in associated header file
//
#include "nsToolboxFrame.h"
#include "nsToolbarFrame.h" // needed for MIME definitions
#include "nsIStyleContext.h"
#include "nsCSSRendering.h"
#include "nsIReflowCommand.h"
#include "nsHTMLIIDs.h"
#include "nsIPresContext.h"
#include "nsIWidget.h"
#include "nsINameSpaceManager.h"
#include "nsIServiceManager.h"
#include "nsWidgetsCID.h"
#include "nsIDragService.h"
#include "nsIDragSession.h"
#include "nsITransferable.h"
#include "nsIFormatConverter.h"
#include "nsCOMPtr.h"
#include "nsIDOMUIEvent.h"
#include "nsIDOMDragListener.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMEventListener.h"
#include "nsISupportsPrimitives.h"
#include "nsISupportsArray.h"
// Drag & Drop, Clipboard Support
static NS_DEFINE_CID(kCDragServiceCID, NS_DRAGSERVICE_CID);
static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID);
static NS_DEFINE_IID(kCDataFlavorCID, NS_DATAFLAVOR_CID);
static NS_DEFINE_IID(kCXIFFormatConverterCID, NS_XIFFORMATCONVERTER_CID);
NS_IMPL_ADDREF(nsToolboxFrame::DragListenerDelegate);
NS_IMPL_RELEASE(nsToolboxFrame::DragListenerDelegate);
NS_IMETHODIMP
nsToolboxFrame::DragListenerDelegate::QueryInterface(REFNSIID aIID, void** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsCOMTypeInfo<nsIDOMDragListener>::GetIID()) ||
aIID.Equals(nsCOMTypeInfo<nsIDOMEventListener>::GetIID()) ||
aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID())) {
*aResult = NS_STATIC_CAST(nsIDOMDragListener*, this);
NS_ADDREF_THIS();
return NS_OK;
}
else {
*aResult = nsnull;
return NS_NOINTERFACE;
}
}
//
// NS_NewToolboxFrame
//
// Creates a new toolbox frame and returns it in |aNewFrame|
//
nsresult
NS_NewToolboxFrame ( nsIFrame** aNewFrame )
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsToolboxFrame* it = new nsToolboxFrame;
if (nsnull == it)
return NS_ERROR_OUT_OF_MEMORY;
//it->SetFlags(aFlags);
*aNewFrame = it;
return NS_OK;
} // NS_NewToolboxFrame
//
// nsToolboxFrame cntr
//
// Init, if necessary
//
nsToolboxFrame :: nsToolboxFrame ( )
: mSumOfToolbarHeights(0), mNumToolbars(0),
mGrippyHilighted(kNoGrippyHilighted),
kCollapsedAtom(dont_AddRef( NS_NewAtom("collapsed"))),
kHiddenAtom(dont_AddRef( NS_NewAtom("hidden"))),
mDragListenerDelegate(nsnull)
{
// we start off vertical
mHorizontal = PR_FALSE;
}
//
// nsToolboxFrame dstr
//
// Cleanup, as necessary
//
nsToolboxFrame :: ~nsToolboxFrame ( )
{
if (mDragListenerDelegate) {
mDragListenerDelegate->NotifyFrameDestroyed();
NS_RELEASE(mDragListenerDelegate);
}
ClearGrippyList ( mGrippies );
}
//
// RefreshStyleContext
//
// Not exactly sure what this does ;)
//
void
nsToolboxFrame :: RefreshStyleContext(nsIPresContext* aPresContext,
nsIAtom * aNewContentPseudo,
nsCOMPtr<nsIStyleContext>* aCurrentStyle,
nsIContent * aContent,
nsIStyleContext* aParentStyle)
{
nsIStyleContext* newStyleContext;
aPresContext->ProbePseudoStyleContextFor(aContent,
aNewContentPseudo,
aParentStyle,
PR_FALSE,
&newStyleContext);
if (newStyleContext != aCurrentStyle->get())
*aCurrentStyle = dont_QueryInterface(newStyleContext);
} // RefreshStyleContext
NS_IMETHODIMP
nsToolboxFrame::GetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext** aStyleContext) const
{
NS_PRECONDITION(nsnull != aStyleContext, "null OUT parameter pointer");
if (aIndex < 0) {
return NS_ERROR_INVALID_ARG;
}
*aStyleContext = nsnull;
switch (aIndex) {
case NS_TOOLBOX_GRIPPY_NORMAL_CONTEXT_INDEX:
*aStyleContext = mGrippyNormalStyle;
NS_IF_ADDREF(*aStyleContext);
break;
case NS_TOOLBOX_GRIPPY_ROLLOVER_CONTEXT_INDEX:
*aStyleContext = mGrippyRolloverStyle;
NS_IF_ADDREF(*aStyleContext);
break;
default:
return NS_ERROR_INVALID_ARG;
}
return NS_OK;
}
NS_IMETHODIMP
nsToolboxFrame::SetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext* aStyleContext)
{
if (aIndex < 0) {
return NS_ERROR_INVALID_ARG;
}
switch (aIndex) {
case NS_TOOLBOX_GRIPPY_NORMAL_CONTEXT_INDEX:
mGrippyNormalStyle = aStyleContext;
break;
case NS_TOOLBOX_GRIPPY_ROLLOVER_CONTEXT_INDEX:
mGrippyRolloverStyle = aStyleContext;
break;
}
return NS_OK;
}
NS_IMETHODIMP
nsToolboxFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsBoxFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
UpdateStyles(&aPresContext);
// Register the delegate as a drag listener.
mDragListenerDelegate = new DragListenerDelegate(this);
if (! mDragListenerDelegate)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mDragListenerDelegate);
nsCOMPtr<nsIContent> content;
rv = GetContent(getter_AddRefs(content));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMEventReceiver> reciever(do_QueryInterface(content));
reciever->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMDragListener*, mDragListenerDelegate), nsIDOMDragListener::GetIID());
return rv;
}
void
nsToolboxFrame::UpdateStyles(nsIPresContext* aPresContext)
{
nsCOMPtr<nsIAtom> grippyRolloverPseudo ( dont_AddRef(NS_NewAtom(":toolbox-rollover")) );
RefreshStyleContext(aPresContext, grippyRolloverPseudo, &mGrippyRolloverStyle, mContent, mStyleContext);
nsCOMPtr<nsIAtom> grippyNormalPseudo ( dont_AddRef(NS_NewAtom(":toolbox-normal")) );
RefreshStyleContext(aPresContext, grippyNormalPseudo, &mGrippyNormalStyle, mContent, mStyleContext);
}
//
// Paint
//
// Paint our background and border like normal frames, but before we draw the
// children, draw our grippies for each toolbar.
//
NS_IMETHODIMP
nsToolboxFrame :: Paint ( nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
// if we aren't visible then we are done.
const nsStyleDisplay* disp = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
if (!disp->mVisible)
return NS_OK;
// take care of bg painting, borders and children
nsresult retVal = nsBoxFrame::Paint ( aPresContext, aRenderingContext, aDirtyRect, aWhichLayer );
// now draw what makes us special
DrawGrippies ( aPresContext, aRenderingContext );
return retVal;
} // Paint
//
// DrawGrippies
//
// Redraws all the grippies in the toolbox by iterating over each toolbar in the DOM
// and figuring out how to draw the grippies based on size/visibility information
//
void
nsToolboxFrame :: DrawGrippies ( nsIPresContext& aPresContext, nsIRenderingContext & aRenderingContext ) const
{
for ( PRInt32 i = 0; i < mGrippies.Count(); ++i ) {
TabInfo* currGrippy = NS_STATIC_CAST(TabInfo*, mGrippies[i]);
PRBool hilight = (mGrippyHilighted == i) ? PR_TRUE : PR_FALSE;
DrawGrippy ( aPresContext, aRenderingContext, currGrippy->mBoundingRect, hilight );
} // for each child
} // DrawGrippies
//
// DrawGrippy
//
// Draw a single grippy in the given rectangle, either with or without rollover feedback.
//
void
nsToolboxFrame :: DrawGrippy ( nsIPresContext& aPresContext, nsIRenderingContext & aRenderingContext,
const nsRect & aBoundingRect, PRBool aDrawHilighted ) const
{
nsCOMPtr<nsIStyleContext> style ( aDrawHilighted ? mGrippyRolloverStyle : mGrippyNormalStyle ) ;
if ( !mGrippyRolloverStyle ) {
#ifdef NS_DEBUG
printf("nsToolboxFrame::DrawGrippy() -- style context null, css file not loaded correctly??\n");
#endif
return; // something must be seriously wrong
}
const nsStyleColor* grippyColor = (const nsStyleColor*)style->GetStyleData(eStyleStruct_Color);
const nsStyleSpacing* grippySpacing = (const nsStyleSpacing*)style->GetStyleData(eStyleStruct_Spacing);
// const nsStyleFont* grippyFont = (const nsStyleFont*)style->GetStyleData(eStyleStruct_Font);
nsToolboxFrame* nonConstSelf = NS_CONST_CAST(nsToolboxFrame*, this);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, nonConstSelf,
aBoundingRect, aBoundingRect, *grippyColor, *grippySpacing, 0, 0);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, nonConstSelf,
aBoundingRect, aBoundingRect, *grippySpacing, style, 0);
} // DrawGrippy
NS_IMETHODIMP
nsToolboxFrame::GetBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize)
{
CalculateGrippies(aPresContext);
return nsBoxFrame::GetBoxInfo(aPresContext, aReflowState, aSize);
}
NS_IMETHODIMP
nsToolboxFrame :: Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult errCode = nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
errCode = ReflowGrippies(aPresContext, aDesiredSize, aReflowState, aStatus);
return errCode;
} // Reflow
// After we have been flowed this should be flowed to place the grippies at there
// physical locations.
nsresult
nsToolboxFrame::ReflowGrippies(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
// get the rect we can place the grippies in. This is inside our borders and debug rect.
nsRect innerRect(0,0,0,0);
GetInnerRect(innerRect);
float p2t;
aPresContext.GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nscoord grippyWidth = kGrippyWidthInPixels * onePixel; // remember to leave room for the grippy on the right
nscoord collapsedGrippyHeight = kCollapsedGrippyHeightInPixels * onePixel;
nsresult errCode = NS_OK;
const PRBool isHorz = IsHorizontal();
// iterate over all visible toolbar frames, moving the associated grippy
// next to the toolbar
mNumToolbars = 0;
nsIFrame* childFrame = mFrames.FirstChild();
while ( childFrame ) {
// get the childs rect and figure out the grippy size
nsCOMPtr<nsIContent> childContent;
childFrame->GetContent(getter_AddRefs(childContent));
nsRect grippyRect;
childFrame->GetRect(grippyRect);
if ( isHorz ) {
grippyRect.y = innerRect.y;
grippyRect.height = grippyWidth;
} else {
grippyRect.x = innerRect.x;
grippyRect.width = grippyWidth;
}
TabInfo *grippyInfo = FindGrippyForToolbar(mGrippies, childContent);
NS_ASSERTION(grippyInfo != 0, "Grippy Info Struct dissapeared!");
NS_ASSERTION(grippyInfo->mCollapsed == 0, "Collapsed toolbar has frame!");
// Set the location of the grippy to the left...
grippyInfo->SetBounds(grippyRect);
errCode = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(errCode == NS_OK, "failed to get next child");
mNumToolbars++;
}
// now move collapsed grippies to the bottom
for ( PRInt32 i = 0; i < mGrippies.Count(); ++i ) {
TabInfo* currGrippy = NS_STATIC_CAST(TabInfo*, mGrippies[i]);
if (currGrippy->mCollapsed) {
// remember we are just inverting the coord system here so in a
// horzontal toolbox our height is our width. Thats why we just use
// height here on both x and y coords.
if ( isHorz )
currGrippy->mBoundingRect.x = aDesiredSize.width - collapsedGrippyHeight;
else
currGrippy->mBoundingRect.y = aDesiredSize.height - collapsedGrippyHeight;
}
}
return errCode;
}
// called to figure out how big our grippies are and how many we have
// this will be called by boxes reflow method.
void
nsToolboxFrame::CalculateGrippies(nsIPresContext& aPresContext)
{
// compute amount (in twips) each toolbar will be offset from the right because of
// the grippy
float p2t;
aPresContext.GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nscoord collapsedGrippyHeight = kCollapsedGrippyHeightInPixels * onePixel;
nscoord collapsedGrippyWidth = kCollapsedGrippyWidthInPixels * onePixel;
const PRBool isHorz = IsHorizontal();
{
nscoord grippyWidth = kGrippyWidthInPixels * onePixel; // remember to leave room for the grippy on the right
// Leave room at the side for the grippies of visible toolbars. Make a margin
// of the appropriate dimensions.
mInset = nsMargin(0,0,0,0);
if ( isHorz ) // Set margins so we have a place for uncollapsed grippies
mInset.top = grippyWidth;
else
mInset.left = grippyWidth;
}
// Save old tabs so we can make newly collapsed bars as wide as they WERE tall. We will
// release the grippies in mGrippies at the very end when we dispose of |oldGrippies|
nsVoidArray oldGrippies, emptyList;
oldGrippies = mGrippies;
mGrippies = emptyList;
// ----- Calculate a new set of grippy states...
// iterate over each content node to see if we can find one with the "collapsed"
// attribute set. If so, we have a collapsed toolbar.
nsAutoString value;
int numCollapsedGrippies = 0;
nscoord grippyPos = 0;
// Get the first child of the toolbox content node
unsigned int contentCounter = 0;
nsCOMPtr<nsIContent> childContent;
nsresult errCode = mContent->ChildAt(contentCounter, *getter_AddRefs(childContent));
NS_ASSERTION(errCode == NS_OK,"failed to get first child");
// iterate over each content node to see if we can find one with the "collapsed"
// attribute set. If so, we have a collapsed toolbar.
while ( childContent ) {
// is this bar collapsed?
value = "";
childContent->GetAttribute(kNameSpaceID_None, kCollapsedAtom, value);
if (value == "true") { // The bar is collapsed!
nscoord grippyWidth;
nscoord grippyHeight;
if ( isHorz ) {
grippyWidth = collapsedGrippyHeight;
grippyHeight = collapsedGrippyWidth;
} else {
grippyWidth = collapsedGrippyWidth;
grippyHeight = collapsedGrippyHeight;
}
TabInfo* oldGrippy = FindGrippyForToolbar ( oldGrippies, childContent );
if ( oldGrippy ) { // Inherit the old size...
if ( isHorz ) { // If laying out children horizontally...
if ( oldGrippy->mCollapsed) // Did it used to be collapsed?
grippyHeight = oldGrippy->mBoundingRect.height; // Copy old width
else
grippyHeight = oldGrippy->mBoundingRect.width; // Else copy old height
} else { // If laying out children vertically...
if ( oldGrippy->mCollapsed ) // Did it used to be collapsed?
grippyWidth = oldGrippy->mBoundingRect.width; // Copy old width
else
grippyWidth = oldGrippy->mBoundingRect.height; // Else copy old height
}
}
if ( isHorz ) {
mGrippies.AppendElement( new TabInfo(childContent, PR_TRUE,
nsRect(0, grippyPos, grippyWidth, grippyHeight)) );
grippyPos += grippyHeight;
} else {
mGrippies.AppendElement( new TabInfo(childContent, PR_TRUE,
nsRect(grippyPos, 0, grippyWidth, grippyHeight)) );
grippyPos += grippyWidth;
}
++numCollapsedGrippies;
} else { // The bar is NOT collapsed!!
mGrippies.AppendElement( new TabInfo(childContent, PR_FALSE) );
}
// next!
++contentCounter;
errCode = mContent->ChildAt(contentCounter, *getter_AddRefs(childContent));
NS_ASSERTION(errCode == NS_OK,"failed to get next child");
}
// if there are any collapsed bars, we need to leave room at the bottom of
// the box for the grippies. Adjust the margins before we reflow the box.
if ( numCollapsedGrippies ) {
if ( isHorz )
mInset.left = collapsedGrippyHeight;
else
mInset.bottom = collapsedGrippyHeight;
}
// make sure we now dispose of the old grippies since we have allocated
// new ones.
ClearGrippyList ( oldGrippies );
}
//
// FindGrippyForToolbar
//
// Utility routine to scan through the grippy list looking for one in the list
// associated with the given content object (which is the toolbar's content object).
//
// Will return nsnull if it cannot find the toolbar.
//
nsToolboxFrame::TabInfo*
nsToolboxFrame :: FindGrippyForToolbar ( nsVoidArray & inList, const nsIContent* inContent ) const
{
for ( PRInt32 i = 0; i < inList.Count(); ++i ) {
TabInfo* currGrippy = NS_STATIC_CAST(TabInfo*, inList[i]);
if ( currGrippy->mToolbar == inContent )
return currGrippy;
}
return nsnull;
} // FindGrippyForToolbar
//
// ClearGrippyList
//
// Since we are assuming the array "owns" the grippies once they go in there,
// we need to make sure that when the list goes away that they are cleaned up. The
// nsVoidArray does not know how to do this, so we need to do it ourselves.
//
void
nsToolboxFrame :: ClearGrippyList ( nsVoidArray & inList )
{
for ( PRInt32 i = 0; i < inList.Count(); ++i ) {
TabInfo* currGrippy = NS_STATIC_CAST(TabInfo*, inList[i]);
delete currGrippy;
}
} // ClearGrippyList
//
// GetInset
//
// Our Reflow() method computes a margin for the grippies and for collased grippies (if
// any). Return this pre-computed margin when asked by the box.
//
void
nsToolboxFrame::GetInset(nsMargin& margin)
{
margin = mInset;
}
//
// GetFrameForPoint
//
// Override to process events in our own frame
//
NS_IMETHODIMP
nsToolboxFrame :: GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame)
{
nsresult retVal = nsHTMLContainerFrame::GetFrameForPoint(aPresContext, aPoint, aFrame);
// returning NS_OK means that we tell the frame finding code that we have something
// and to stop looking elsewhere for a frame.
if ( aFrame && *aFrame == this )
retVal = NS_OK;
else if ( retVal != NS_OK ) {
*aFrame = this;
retVal = NS_OK;
}
return retVal;
} // GetFrameForPoint
//
// HandleEvent
//
//
NS_IMETHODIMP
nsToolboxFrame :: HandleEvent ( nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
if ( !aEvent )
return nsEventStatus_eIgnore;
switch ( aEvent->message ) {
case NS_MOUSE_LEFT_CLICK:
// BUG 3752 aEvent->point is invalid here.
break;
case NS_MOUSE_LEFT_BUTTON_UP:
OnMouseLeftClick ( &aPresContext, aEvent->point );
break;
case NS_MOUSE_MOVE:
OnMouseMove ( &aPresContext, aEvent->point );
break;
case NS_MOUSE_EXIT:
OnMouseExit ( &aPresContext);
break;
default:
break;
} // case of which event
return nsEventStatus_eIgnore;
} // HandleEvent
//
// ConvertToLocalPoint
//
// Given a point in the coordinate system of the parent view, convert to a point in the
// frame's local coordinate system.
//
void
nsToolboxFrame :: ConvertToLocalPoint ( nsIPresContext* aPresContext, nsPoint & ioPoint )
{
nsIView* view = nsnull; // note: |view| not AddRef'd
nsPoint offset;
if ( GetOffsetFromView(aPresContext, offset, &view) == NS_OK )
ioPoint -= offset;
} // ConvertToLocalPoint
//
// OnMouseMove
//
// Handle mouse move events for hilighting and unhilighting the grippies. |aMouseLoc|
// is not in local frame coordinates.
//
void
nsToolboxFrame :: OnMouseMove ( nsIPresContext* aPresContext, nsPoint & aMouseLoc )
{
nsPoint localMouseLoc = aMouseLoc;
ConvertToLocalPoint ( aPresContext, localMouseLoc );
for ( int i = 0; i < mGrippies.Count(); ++i ) {
TabInfo* currGrippy = NS_STATIC_CAST(TabInfo*, mGrippies[i]);
if ( currGrippy->mBoundingRect.Contains(localMouseLoc) ) {
if ( i != mGrippyHilighted ) {
// unhilight the old one
if ( mGrippyHilighted != kNoGrippyHilighted ) {
TabInfo* hilightedGrippy = NS_STATIC_CAST(TabInfo*, mGrippies[mGrippyHilighted]);
Invalidate ( aPresContext, hilightedGrippy->mBoundingRect, PR_FALSE );
}
// hilight the new one and remember it
mGrippyHilighted = i;
Invalidate ( aPresContext, currGrippy->mBoundingRect, PR_FALSE );
} // if in a new tab
}
} // for each toolbar
} // OnMouseMove
//
// OnMouseLeftClick
//
// Check if a click is in a grippy and expand/collapse appropriately. |aMouseLoc|
// is not in local frame coordinates.
//
void
nsToolboxFrame :: OnMouseLeftClick ( nsIPresContext* aPresContext, nsPoint & aMouseLoc )
{
nsPoint localMouseLoc = aMouseLoc;
ConvertToLocalPoint ( aPresContext, localMouseLoc );
for ( int i = 0; i < mGrippies.Count(); ++i ) {
TabInfo* currGrippy = NS_STATIC_CAST(TabInfo*, mGrippies[i]);
if ( currGrippy->mBoundingRect.Contains(localMouseLoc) ) {
if ( currGrippy->mCollapsed )
ExpandToolbar ( *currGrippy );
else
CollapseToolbar ( *currGrippy );
// don't keep repeating this process since toolbars have now be
// relaid out and a new toolbar may be under the current mouse
// location!
break;
}
}
} // OnMouseLeftClick
//
// OnMouseExit
//
// Update the grippies that may have been hilighted while the mouse was within the
// manager.
//
void
nsToolboxFrame :: OnMouseExit (nsIPresContext* aPresContext)
{
if ( mGrippyHilighted != kNoGrippyHilighted ) {
TabInfo* hilightedGrippy = NS_STATIC_CAST(TabInfo*, mGrippies[mGrippyHilighted]);
Invalidate ( aPresContext, hilightedGrippy->mBoundingRect, PR_FALSE );
mGrippyHilighted = kNoGrippyHilighted;
}
} // OnMouseExit
//
// CollapseToolbar
//
// Given the tab that was clicked on, collapse its corresponding toolbar. This
// assumes that the tab is expanded.
//
void
nsToolboxFrame :: CollapseToolbar ( TabInfo & inTab )
{
if ( inTab.mToolbar ) {
#ifdef NS_DEBUG
printf("CollapseToolbar:: collapsing\n");
#endif
nsresult errCode = inTab.mToolbar->SetAttribute ( kNameSpaceID_None, kCollapsedAtom, "true", PR_TRUE );
#ifdef NS_DEBUG
if ( errCode )
printf("Problem setting collapsed attribute while collapsing toolbar\n");
#endif
}
} // CollapseToolbar
//
// ExpandToolbar
//
// Given the collapsed (horizontal) tab that was clicked on, expand its
// corresponding toolbar. This assumes the tab is collapsed.
//
void
nsToolboxFrame :: ExpandToolbar ( TabInfo & inTab )
{
// nsresult errCode = mContent->UnsetAttribute ( kNameSpaceID_None, kCollapsedAtom, PR_TRUE );
nsresult errCode = inTab.mToolbar->SetAttribute ( kNameSpaceID_None, kCollapsedAtom, "false", PR_TRUE );
#ifdef NS_DEBUG
if ( errCode )
printf("Problem clearing collapsed attribute while expanding toolbar\n");
#endif
} // ExpandToolbar
////////////////////////////////////////////////////////////////////////
nsresult
nsToolboxFrame::HandleEvent(nsIDOMEvent* aEvent)
{
//printf("nsToolbarDragListener::HandleEvent\n");
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
nsresult
nsToolboxFrame::DragEnter(nsIDOMEvent* aDragEvent)
{
nsIDragService* dragService;
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
nsIDragService::GetIID(),
(nsISupports **)&dragService);
if ( NS_SUCCEEDED(rv) ) {
nsCOMPtr<nsIDragSession> dragSession(do_QueryInterface(dragService));
if ( dragSession ) {
PRBool flavorSupported = PR_FALSE;
dragSession->IsDataFlavorSupported(TOOLBAR_MIME, &flavorSupported);
if ( flavorSupported ) {
dragSession->SetCanDrop(PR_TRUE);
rv = NS_ERROR_BASE; // consume event
}
}
nsServiceManager::ReleaseService(kCDragServiceCID, dragService);
} else {
rv = NS_OK;
}
return rv;
}
////////////////////////////////////////////////////////////////////////
nsresult
nsToolboxFrame::DragOver(nsIDOMEvent* aDragEvent)
{
// now tell the drag session whether we can drop here
nsIDragService* dragService;
nsresult rv = nsServiceManager::GetService(kCDragServiceCID, nsIDragService::GetIID(),
(nsISupports **)&dragService);
if ( NS_SUCCEEDED(rv) ) {
nsCOMPtr<nsIDragSession> dragSession(do_QueryInterface(dragService));
if ( dragSession ) {
PRBool flavorSupported = PR_FALSE;
dragSession->IsDataFlavorSupported(TOOLBAR_MIME, &flavorSupported);
if ( flavorSupported ) {
// Right here you need to figure out where the mouse is
// and whether you can drop here
dragSession->SetCanDrop(PR_TRUE);
rv = NS_ERROR_BASE; // consume event
}
}
nsServiceManager::ReleaseService(kCDragServiceCID, dragService);
}
// NS_OK means event is NOT consumed
return rv;
}
////////////////////////////////////////////////////////////////////////
nsresult
nsToolboxFrame::DragExit(nsIDOMEvent* aDragEvent)
{
return NS_ERROR_BASE; // consumes event
}
////////////////////////////////////////////////////////////////////////
nsresult
nsToolboxFrame::DragDrop(nsIDOMEvent* aMouseEvent)
{
// Create drag service for getting state of drag
nsIDragService* dragService;
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
nsIDragService::GetIID(),
(nsISupports **)&dragService);
if (NS_OK == rv) {
nsCOMPtr<nsIDragSession> dragSession(do_QueryInterface(dragService));
if (dragSession) {
// Create transferable for getting the drag data
nsCOMPtr<nsITransferable> trans;
rv = nsComponentManager::CreateInstance(kCTransferableCID, nsnull,
nsITransferable::GetIID(),
(void**) getter_AddRefs(trans));
if ( NS_SUCCEEDED(rv) && trans ) {
// Add the toolbar Flavor to the transferable, because that is the only type of data we are
// looking for at the moment.
trans->AddDataFlavor(TOOLBAR_MIME);
// Fill the transferable with data for each drag item in succession
PRUint32 numItems = 0;
if (NS_SUCCEEDED(dragSession->GetNumDropItems(&numItems))) {
//printf("Num Drop Items %d\n", numItems);
PRUint32 i;
for (i=0;i<numItems;++i) {
if (NS_SUCCEEDED(dragSession->GetData(trans, i))) {
// Get the string data out of the transferable as a nsISupportsString.
nsCOMPtr<nsISupports> data;
PRUint32 len;
char* whichFlavor = nsnull;
trans->GetAnyTransferData(&whichFlavor, getter_AddRefs(data), &len);
nsCOMPtr<nsISupportsString> dataAsString ( do_QueryInterface(data) );
// If the string was not empty then make it so.
if ( dataAsString ) {
char* stuffToPaste;
dataAsString->ToString ( &stuffToPaste );
printf("Dropped: %s\n", stuffToPaste);
dragSession->SetCanDrop(PR_TRUE);
}
nsAllocator::Free ( whichFlavor );
}
} // foreach drag item
}
} // if valid transferable
} // if valid drag session
nsServiceManager::ReleaseService(kCDragServiceCID, dragService);
} // if valid drag service
return NS_ERROR_BASE; // consume the event;
}

View File

@@ -0,0 +1,226 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
//
// Mike Pinkerton
// Netscape Communications
//
// nsToolboxFrame is a layout object that contains one or more toolbar frames
// (specified as children in the DOM). These toolbars are laid out one on top
// of the other, and can be of varying heights but are all of the same width
// (the full width of the toolbox). Each toolbar is associated with a "grippy"
// which can be used to either collapse a particular toolbar or as a handle to
// pick up and move a toolbar to a new position within the toolbox. When toolbars
// are collapsed, it's grippy is moved to the bottom of the box and laid on
// its side. Clicking again on the grippy will reinstate the toolbar to its previous
// position in the toolbox.
//
// As mentioned above, the toolbox expects its toolbars to be its children in
// the DOM. The exact structure of the children is documented on:
// http://www.mozilla.org/xpfe/DMWSpecNew.html
//
#ifndef nsToolBoxFrame_h___
#define nsToolBoxFrame_h___
#include "nsIDOMDragListener.h"
#include "nsHTMLContainerFrame.h"
#include "nsIStyleContext.h"
#include "nsIContent.h"
#include "nsXULAtoms.h"
#include "nsCOMPtr.h"
#include "nsBoxFrame.h"
#define NS_TOOLBOX_GRIPPY_NORMAL_CONTEXT_INDEX 0
#define NS_TOOLBOX_GRIPPY_ROLLOVER_CONTEXT_INDEX 1
class nsToolboxFrame : public nsBoxFrame
{
public:
friend nsresult NS_NewToolboxFrame(nsIFrame** aNewFrame);
// nsIHTMLReflow overrides
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD GetBoxInfo(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize);
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext** aStyleContext) const;
NS_IMETHOD SetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext* aStyleContext);
// Overridden to capture events
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame);
/*BEGIN implementations of dragevent handler interface*/
virtual nsresult HandleEvent(nsIDOMEvent* aEvent);
virtual nsresult DragEnter(nsIDOMEvent* aDragEvent);
virtual nsresult DragOver(nsIDOMEvent* aDragEvent);
virtual nsresult DragExit(nsIDOMEvent* aDragEvent);
virtual nsresult DragDrop(nsIDOMEvent* aDragEvent);
virtual nsresult DragGesture(nsIDOMEvent* aDragEvent) { return NS_OK; }
/*END implementations of dragevent handler interface*/
protected:
enum { kGrippyWidthInPixels = 10, kCollapsedGrippyHeightInPixels = 10, kCollapsedGrippyWidthInPixels = 50 } ;
enum { kNoGrippyHilighted = -1 } ;
struct TabInfo {
TabInfo( nsIContent * inContent, PRBool inCollapsed,
const nsRect &inBounds = nsRect(0,0,0,0))
: mToolbar(inContent),
mBoundingRect(inBounds),
mCollapsed(inCollapsed)
{
}
void SetBounds(const nsRect &inBounds) { mBoundingRect = inBounds; }
nsIContent* mToolbar; // content object associated w/ toolbar frame. We don't own it.
nsRect mBoundingRect;
PRBool mCollapsed;
};
nsToolboxFrame();
virtual ~nsToolboxFrame();
virtual void UpdateStyles(nsIPresContext* aPresContext);
virtual void CalculateGrippies(nsIPresContext& aPresContext);
virtual nsresult ReflowGrippies(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
void RefreshStyleContext(nsIPresContext* aPresContext,
nsIAtom * aNewContentPseudo,
nsCOMPtr<nsIStyleContext>* aCurrentStyle,
nsIContent * aContent,
nsIStyleContext* aParentStyle) ;
void DrawGrippies ( nsIPresContext& aPresContext, nsIRenderingContext & aContext ) const ;
void DrawGrippy ( nsIPresContext& aPresContext, nsIRenderingContext & aContext,
const nsRect & aBoundingRect, PRBool aDrawHilighted ) const ;
void CollapseToolbar ( TabInfo & inTab ) ;
void ExpandToolbar ( TabInfo & inTab ) ;
void ConvertToLocalPoint ( nsIPresContext* aPresContext, nsPoint & ioPoint ) ;
void OnMouseMove ( nsIPresContext* aPresContext, nsPoint & aMouseLoc ) ;
void OnMouseExit ( nsIPresContext* aPresContext ) ;
void OnMouseLeftClick ( nsIPresContext* aPresContext, nsPoint & aMouseLoc ) ;
// utility routines
TabInfo* FindGrippyForToolbar ( nsVoidArray & inList, const nsIContent* inContent ) const ;
void ClearGrippyList ( nsVoidArray & inList ) ;
// style context for the normal state and rollover state of grippies
nsCOMPtr<nsIStyleContext> mGrippyNormalStyle;
nsCOMPtr<nsIStyleContext> mGrippyRolloverStyle;
nsMargin mInset;
virtual void GetInset(nsMargin& margin);
unsigned long mSumOfToolbarHeights;
nsVoidArray mGrippies; // list of all active grippies
unsigned short mNumToolbars;
short mGrippyHilighted; // used to indicate which grippy the mouse is inside
const nsCOMPtr<nsIAtom> kCollapsedAtom ;
const nsCOMPtr<nsIAtom> kHiddenAtom ;
class DragListenerDelegate : public nsIDOMDragListener
{
protected:
nsToolboxFrame* mFrame;
public:
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIDOMEventListener interface
virtual nsresult HandleEvent(nsIDOMEvent* aEvent)
{
return mFrame ? mFrame->HandleEvent(aEvent) : NS_OK;
}
virtual nsresult DragGesture(nsIDOMEvent* aEvent)
{
return mFrame ? mFrame->DragGesture(aEvent) : NS_OK;
}
// nsIDOMDragListener interface
virtual nsresult DragEnter(nsIDOMEvent* aMouseEvent)
{
return mFrame ? mFrame->DragEnter(aMouseEvent) : NS_OK;
}
virtual nsresult DragOver(nsIDOMEvent* aMouseEvent)
{
return mFrame ? mFrame->DragOver(aMouseEvent) : NS_OK;
}
virtual nsresult DragExit(nsIDOMEvent* aMouseEvent)
{
return mFrame ? mFrame->DragExit(aMouseEvent) : NS_OK;
}
virtual nsresult DragDrop(nsIDOMEvent* aMouseEvent)
{
return mFrame ? mFrame->DragDrop(aMouseEvent) : NS_OK;
}
// Implementation methods
DragListenerDelegate(nsToolboxFrame* aFrame) : mFrame(aFrame)
{
NS_INIT_REFCNT();
}
virtual ~DragListenerDelegate() {}
void NotifyFrameDestroyed() { mFrame = nsnull; }
};
DragListenerDelegate* mDragListenerDelegate;
// pass-by-value not allowed for a toolbox because it corresponds 1-to-1
// with an element in the UI.
nsToolboxFrame ( const nsToolboxFrame& aFrame ) ; // DO NOT IMPLEMENT
nsToolboxFrame& operator= ( const nsToolboxFrame& aFrame ) ; // DO NOT IMPLEMENT
}; // class nsToolboxFrame
#endif

View File

@@ -0,0 +1,458 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsIDOMElement.h"
#include "nsINameSpaceManager.h"
#include "nsHTMLAtoms.h"
#include "nsTreeCellFrame.h"
#include "nsTreeFrame.h"
#include "nsTreeRowFrame.h"
#include "nsIStyleContext.h"
#include "nsIPresContext.h"
#include "nsIPresShell.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIStyleSet.h"
#include "nsIViewManager.h"
#include "nsCSSRendering.h"
#include "nsXULAtoms.h"
#include "nsCOMPtr.h"
#include "nsINameSpaceManager.h"
//
// NS_NewTreeCellFrame
//
// Creates a new tree cell frame
//
nsresult
NS_NewTreeCellFrame (nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsTreeCellFrame* theFrame = new nsTreeCellFrame();
if (theFrame == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = theFrame;
return NS_OK;
} // NS_NewTreeCellFrame
// Constructor
nsTreeCellFrame::nsTreeCellFrame()
:nsTableCellFrame() { mAllowEvents = PR_FALSE; mIsHeader = PR_FALSE; mAnonymousContent = nsnull; }
// Destructor
nsTreeCellFrame::~nsTreeCellFrame()
{
}
NS_IMETHODIMP
nsTreeCellFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsTableCellFrame::Init(aPresContext, aContent, aParent, aContext,
aPrevInFlow);
// Figure out if we allow events.
nsAutoString attrValue;
nsresult result = aContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::allowevents, attrValue);
attrValue.ToLowerCase();
PRBool allowEvents = (result == NS_CONTENT_ATTR_NO_VALUE ||
(result == NS_CONTENT_ATTR_HAS_VALUE && attrValue=="true"));
SetAllowEvents(allowEvents);
// Determine if we're a column header or not.
// Get row group frame
nsIFrame* rowGroupFrame = nsnull;
aParent->GetParent(&rowGroupFrame);
if (rowGroupFrame != nsnull)
{
// Get the display type of the row group frame and see if it's a header or body
nsCOMPtr<nsIStyleContext> parentContext;
rowGroupFrame->GetStyleContext(getter_AddRefs(parentContext));
if (parentContext)
{
const nsStyleDisplay* display = (const nsStyleDisplay*)
parentContext->GetStyleData(eStyleStruct_Display);
if (display->mDisplay == NS_STYLE_DISPLAY_TABLE_HEADER_GROUP)
{
mIsHeader = PR_TRUE;
}
else mIsHeader = PR_FALSE;
// Get the table frame.
nsTableFrame* tableFrame = nsnull;
rv = nsTableFrame::GetTableFrame(rowGroupFrame, tableFrame);
if (NS_FAILED(rv) || (nsnull == tableFrame)) {
return rv;
}
mTreeFrame = (nsTreeFrame*)tableFrame;
}
}
return rv;
}
NS_IMETHODIMP nsTreeCellFrame::AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint)
{
nsresult rv = nsTableCellFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aHint);
if (mAnonymousContent && (aAttribute == nsHTMLAtoms::align || aAttribute == nsXULAtoms::crop
|| aAttribute == nsHTMLAtoms::value))
{
nsAutoString value;
// XXX should check if attribute has been removed
mContent->GetAttribute(kNameSpaceID_None, aAttribute, value);
mAnonymousContent->SetAttribute(kNameSpaceID_None, aAttribute, value, PR_TRUE);
}
return rv;
}
nsTableFrame* nsTreeCellFrame::GetTreeFrame()
{
return mTreeFrame;
}
NS_METHOD nsTreeCellFrame::Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = nsTableCellFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
return rv;
}
NS_IMETHODIMP
nsTreeCellFrame::GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame)
{
if (mAllowEvents)
{
return nsTableCellFrame::GetFrameForPoint(aPresContext, aPoint, aFrame);
}
else
{
nsresult result = nsTableCellFrame::GetFrameForPoint(aPresContext, aPoint, aFrame);
nsCOMPtr<nsIContent> content;
if (*aFrame) {
(*aFrame)->GetContent(getter_AddRefs(content));
if (content) {
// This allows selective overriding for subcontent.
nsAutoString value;
content->GetAttribute(kNameSpaceID_None, nsXULAtoms::allowevents, value);
if (value == "true")
return result;
}
}
*aFrame = this; // Capture all events so that we can perform selection and expand/collapse.
return NS_OK;
}
}
NS_IMETHODIMP
nsTreeCellFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
aEventStatus = nsEventStatus_eConsumeDoDefault;
if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN) {
if (((nsMouseEvent*)aEvent)->clickCount == 2)
HandleDoubleClickEvent(aPresContext, aEvent, aEventStatus);
else
HandleMouseDownEvent(aPresContext, aEvent, aEventStatus);
}
else if (aEvent->message == NS_MOUSE_ENTER)
HandleMouseEnterEvent(aPresContext, aEvent, aEventStatus);
else if (aEvent->message == NS_MOUSE_EXIT)
HandleMouseExitEvent(aPresContext, aEvent, aEventStatus);
else if (aEvent->message == NS_MOUSE_LEFT_DOUBLECLICK)
HandleDoubleClickEvent(aPresContext, aEvent, aEventStatus);
return NS_OK;
}
nsresult
nsTreeCellFrame::HandleMouseDownEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
if (mIsHeader) {
nsTableColFrame* leftFlex = nsnull;
nsPoint point = ((nsMouseEvent*)aEvent)->point;
if (CanResize(point, &leftFlex))
{
// Begin capturing events.
nsIFrame* frame;
GetParent(&frame);
nsTreeRowFrame* treeRow = (nsTreeRowFrame*)frame;
treeRow->HeaderDrag(&aPresContext, PR_TRUE);
// Inform the tree row of the flexing column
treeRow->SetFlexingColumn(leftFlex);
nsRect rect;
GetRect(rect);
treeRow->SetHeaderPosition(point.x);
}
}
else
{
// Perform a selection
if (((nsMouseEvent *)aEvent)->isShift)
mTreeFrame->RangedSelection(aPresContext, this); // Applying a ranged selection.
#ifdef XP_MAC
else if (((nsMouseEvent *)aEvent)->isMeta)
mTreeFrame->ToggleSelection(aPresContext, this);
#else
else if (((nsMouseEvent *)aEvent)->isControl)
mTreeFrame->ToggleSelection(aPresContext, this); // Applying a toggle selection.
#endif
else mTreeFrame->SetSelection(aPresContext, this); // Doing a single selection only.
}
return NS_OK;
}
nsresult
nsTreeCellFrame::HandleMouseEnterEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
if (mIsHeader)
{
// Nothing to do?
}
else
{
// Set our hover to true
Hover(aPresContext, PR_TRUE);
}
return NS_OK;
}
nsresult
nsTreeCellFrame::HandleMouseExitEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
if (mIsHeader)
{
}
else
{
// Set our hover to false
Hover(aPresContext, PR_FALSE);
}
return NS_OK;
}
PRBool
nsTreeCellFrame::CanResize(nsPoint& aPoint, nsTableColFrame** aResult) {
nsRect rect;
GetRect(rect);
PRInt32 diff = (rect.x + rect.width) - aPoint.x;
nsCOMPtr<nsIContent> parent;
mContent->GetParent(*getter_AddRefs(parent));
PRInt32 index;
parent->IndexOf(mContent, index);
PRInt32 count;
parent->ChildCount(count);
PRBool onLeftEdge = (index > 0 && (rect.width - diff) <= 90);
PRBool onRightEdge = (index < (count-1) && diff <= 90);
if (onLeftEdge || onRightEdge) {
// We're over the right place.
// Ensure that we have flexible columns to the left and to the right.
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
nsTreeFrame* treeFrame = (nsTreeFrame*)tableFrame;
if (onLeftEdge)
index--;
return (treeFrame->ContainsFlexibleColumn(0, index, aResult) &&
treeFrame->ContainsFlexibleColumn(index+1, count-1, nsnull));
}
return PR_FALSE;
}
NS_IMETHODIMP
nsTreeCellFrame::GetCursor(nsIPresContext& aPresContext,
nsPoint& aPoint,
PRInt32& aCursor)
{
if (mIsHeader) {
// Figure out if the point is over the resize stuff.
nsTableColFrame* dummy = nsnull;
if (CanResize(aPoint, &dummy)) {
aCursor = NS_STYLE_CURSOR_W_RESIZE;
}
else {
aCursor = NS_STYLE_CURSOR_DEFAULT;
}
}
else aCursor = NS_STYLE_CURSOR_DEFAULT;
return NS_OK;
}
void
nsTreeCellFrame::ToggleOpenClose()
{
if (!mIsHeader)
{
// Perform an expand/collapse
// Iterate up the chain to the row and then to the item.
nsCOMPtr<nsIContent> treeItemContent;
nsCOMPtr<nsIContent> treeRowContent;
mContent->GetParent(*getter_AddRefs(treeRowContent));
treeRowContent->GetParent(*getter_AddRefs(treeItemContent));
nsCOMPtr<nsIDOMElement> treeItem( do_QueryInterface(treeItemContent) );
NS_ASSERTION(treeItem, "not a DOM element");
if (! treeItem)
return;
// Take the tree item content and toggle the value of its open attribute.
nsAutoString attrValue;
treeItem->GetAttribute("open", attrValue);
attrValue.ToLowerCase();
PRBool isExpanded = (attrValue=="true");
if (isExpanded)
{
// We're collapsing and need to remove frames from the flow.
treeItem->RemoveAttribute("open");
}
else
{
// We're expanding and need to add frames to the flow.
treeItem->SetAttribute("open", "true");
}
}
}
void
nsTreeCellFrame::Open()
{
if (!mIsHeader)
{
// Perform an expand/collapse
// Iterate up the chain to the row and then to the item.
nsCOMPtr<nsIContent> treeItemContent;
nsCOMPtr<nsIContent> treeRowContent;
mContent->GetParent(*getter_AddRefs(treeRowContent));
treeRowContent->GetParent(*getter_AddRefs(treeItemContent));
nsCOMPtr<nsIDOMElement> treeItem( do_QueryInterface(treeItemContent) );
NS_ASSERTION(treeItem, "not a DOM element");
if (! treeItem)
return;
// Take the tree item content and toggle the value of its open attribute.
nsAutoString attrValue;
treeItem->GetAttribute("open", attrValue);
attrValue.ToLowerCase();
PRBool isExpanded = (attrValue=="true");
if (!isExpanded) {
// We're expanding and need to add frames to the flow.
treeItem->SetAttribute("open", "true");
}
}
}
void
nsTreeCellFrame::Close()
{
if (!mIsHeader)
{
// Perform an expand/collapse
// Iterate up the chain to the row and then to the item.
nsCOMPtr<nsIContent> treeItemContent;
nsCOMPtr<nsIContent> treeRowContent;
mContent->GetParent(*getter_AddRefs(treeRowContent));
treeRowContent->GetParent(*getter_AddRefs(treeItemContent));
nsCOMPtr<nsIDOMElement> treeItem( do_QueryInterface(treeItemContent) );
NS_ASSERTION(treeItem, "not a DOM element");
if (! treeItem)
return;
// Take the tree item content and toggle the value of its open attribute.
nsAutoString attrValue;
treeItem->GetAttribute("open", attrValue);
attrValue.ToLowerCase();
PRBool isExpanded = (attrValue=="true");
if (isExpanded) {
// We're expanding and need to add frames to the flow.
treeItem->RemoveAttribute("open");
}
}
}
nsresult
nsTreeCellFrame::HandleDoubleClickEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
ToggleOpenClose();
return NS_OK;
}
void nsTreeCellFrame::Hover(nsIPresContext& aPresContext, PRBool isHover, PRBool notifyForReflow)
{
nsCOMPtr<nsIAtom> kHoverAtom(dont_AddRef(NS_NewAtom("hover")));
nsCOMPtr<nsIContent> rowContent;
nsCOMPtr<nsIContent> itemContent;
mContent->GetParent(*getter_AddRefs(rowContent));
rowContent->GetParent(*getter_AddRefs(itemContent));
if (isHover)
{
// We're selecting the node.
mContent->SetAttribute(kNameSpaceID_None, kHoverAtom, "true", notifyForReflow);
rowContent->SetAttribute(kNameSpaceID_None, kHoverAtom, "true", notifyForReflow);
itemContent->SetAttribute(kNameSpaceID_None, kHoverAtom, "true", notifyForReflow);
}
else
{
// We're deselecting the node.
mContent->UnsetAttribute(kNameSpaceID_None, kHoverAtom, notifyForReflow);
rowContent->UnsetAttribute(kNameSpaceID_None, kHoverAtom, notifyForReflow);
itemContent->UnsetAttribute(kNameSpaceID_None, kHoverAtom, notifyForReflow);
}
}
NS_IMETHODIMP
nsTreeCellFrame::Destroy(nsIPresContext& aPresContext)
{
return nsTableCellFrame::Destroy(aPresContext);
}

View File

@@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsTableCellFrame.h"
class nsTableColFrame;
class nsTreeFrame;
class nsTreeCellFrame : public nsTableCellFrame
{
public:
friend nsresult NS_NewTreeCellFrame(nsIFrame** aNewFrame);
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint);
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint, // Overridden to capture events
nsIFrame** aFrame);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow); // Overridden to set whether we're a column header
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
NS_IMETHOD GetCursor(nsIPresContext& aPresContext,
nsPoint& aPoint,
PRInt32& aCursor);
void Hover(nsIPresContext& presContext, PRBool isHover, PRBool notifyForReflow = PR_TRUE);
nsTableFrame* GetTreeFrame();
void SetAllowEvents(PRBool allowEvents) { mAllowEvents = allowEvents; };
void SetAnonymousContent(nsIContent* aAnonymousContent) { mAnonymousContent = aAnonymousContent; };
void ToggleOpenClose();
void Open();
void Close();
protected:
nsTreeCellFrame();
virtual ~nsTreeCellFrame();
nsresult HandleMouseDownEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
nsresult HandleMouseEnterEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
nsresult HandleMouseExitEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
nsresult HandleDoubleClickEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
PRBool CanResize(nsPoint& aPoint, nsTableColFrame** aResult);
NS_IMETHOD DidSetStyleContext(nsIPresContext* aPresContext) { return NS_OK; };
protected:
// Data members
PRBool mIsHeader; // Whether or not we're a column header
nsTreeFrame* mTreeFrame; // Our parent tree frame.
PRBool mAllowEvents; // Whether we let events go through.
nsIContent* mAnonymousContent; // Our anonymous titledbutton [WEAK ref]
}; // class nsTableCellFrame

View File

@@ -0,0 +1,430 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsCOMPtr.h"
#include "nsTreeFrame.h"
#include "nsIStyleContext.h"
#include "nsIContent.h"
#include "nsCSSRendering.h"
#include "nsTreeCellFrame.h"
#include "nsTableColFrame.h"
#include "nsCellMap.h"
#include "nsIDOMXULTreeElement.h"
#include "nsINameSpaceManager.h"
#include "nsTreeRowGroupFrame.h"
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXULTreeElement.h"
#include "nsTreeTwistyListener.h"
#include "nsIPresContext.h"
#include "nsIPresShell.h"
#include "nsIReflowCommand.h"
#include "nsHTMLParts.h"
//
// NS_NewTreeFrame
//
// Creates a new tree frame
//
nsresult
NS_NewTreeFrame (nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsTreeFrame* it = new nsTreeFrame;
if (!it)
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
} // NS_NewTreeFrame
// Constructor
nsTreeFrame::nsTreeFrame()
:nsTableFrame(),mSlatedForReflow(PR_FALSE), mTwistyListener(nsnull), mGeneration(0), mUseGeneration(PR_TRUE) { }
// Destructor
nsTreeFrame::~nsTreeFrame()
{
}
void nsTreeFrame::SetSelection(nsIPresContext& aPresContext, nsTreeCellFrame* aFrame)
{
nsCOMPtr<nsIContent> cellContent;
aFrame->GetContent(getter_AddRefs(cellContent));
if (!cellContent) return;
nsCOMPtr<nsIContent> rowContent;
cellContent->GetParent(*getter_AddRefs(rowContent));
nsCOMPtr<nsIContent> itemContent;
rowContent->GetParent(*getter_AddRefs(itemContent));
nsCOMPtr<nsIDOMXULTreeElement> treeElement = do_QueryInterface(mContent);
nsCOMPtr<nsIDOMXULElement> cellElement = do_QueryInterface(cellContent);
nsCOMPtr<nsIDOMXULElement> itemElement = do_QueryInterface(itemContent);
nsCOMPtr<nsIAtom> kSuppressSelectChange = dont_AddRef(NS_NewAtom("suppressonselect"));
mContent->SetAttribute(kNameSpaceID_None, kSuppressSelectChange, "true", PR_FALSE);
treeElement->SelectItem(itemElement);
mContent->UnsetAttribute(kNameSpaceID_None, kSuppressSelectChange, PR_FALSE);
treeElement->SelectCell(cellElement);
}
void nsTreeFrame::ToggleSelection(nsIPresContext& aPresContext, nsTreeCellFrame* aFrame)
{
nsCOMPtr<nsIContent> cellContent;
aFrame->GetContent(getter_AddRefs(cellContent));
nsCOMPtr<nsIContent> rowContent;
cellContent->GetParent(*getter_AddRefs(rowContent));
nsCOMPtr<nsIContent> itemContent;
rowContent->GetParent(*getter_AddRefs(itemContent));
nsCOMPtr<nsIDOMXULTreeElement> treeElement = do_QueryInterface(mContent);
nsCOMPtr<nsIDOMXULElement> cellElement = do_QueryInterface(cellContent);
nsCOMPtr<nsIDOMXULElement> itemElement = do_QueryInterface(itemContent);
nsCOMPtr<nsIAtom> kSuppressSelectChange = dont_AddRef(NS_NewAtom("suppressonselect"));
mContent->SetAttribute(kNameSpaceID_None, kSuppressSelectChange, "true", PR_FALSE);
treeElement->ToggleItemSelection(itemElement);
mContent->UnsetAttribute(kNameSpaceID_None, kSuppressSelectChange, PR_FALSE);
treeElement->ToggleCellSelection(cellElement);
}
void nsTreeFrame::RangedSelection(nsIPresContext& aPresContext, nsTreeCellFrame* pEndFrame)
{
// XXX Re-implement!
}
void
nsTreeFrame::GetTreeBody(nsTreeRowGroupFrame** aResult)
{
nsIFrame* curr = mFrames.FirstChild();
while (curr) {
nsCOMPtr<nsIContent> content;
curr->GetContent(getter_AddRefs(content));
if (content) {
nsCOMPtr<nsIAtom> tag;
content->GetTag(*getter_AddRefs(tag));
if (tag && tag.get() == nsXULAtoms::treechildren) {
// This is our actual treechildren frame.
nsTreeRowGroupFrame* rowGroup = (nsTreeRowGroupFrame*)curr; // XXX I am evil.
*aResult = rowGroup;
return;
}
}
curr->GetNextSibling(&curr);
}
}
NS_IMETHODIMP
nsTreeFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
aEventStatus = nsEventStatus_eConsumeDoDefault;
if (aEvent->message == NS_KEY_DOWN) {
nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
PRUint32 keyCode = keyEvent->keyCode;
if (keyCode == NS_VK_UP ||
keyCode == NS_VK_DOWN ||
keyCode == NS_VK_LEFT ||
keyCode == NS_VK_RIGHT ||
keyCode == NS_VK_ENTER) {
// Get our treechildren child frame.
nsTreeRowGroupFrame* treeRowGroup = nsnull;
GetTreeBody(&treeRowGroup);
if (!treeRowGroup)
return NS_OK; // No tree body. Just bail.
nsCOMPtr<nsIDOMXULTreeElement> treeElement = do_QueryInterface(mContent);
nsCOMPtr<nsIDOMNodeList> itemNodeList;
nsCOMPtr<nsIDOMNodeList> cellNodeList;
treeElement->GetSelectedItems(getter_AddRefs(itemNodeList));
treeElement->GetSelectedCells(getter_AddRefs(cellNodeList));
PRUint32 itemLength;
PRUint32 cellLength;
itemNodeList->GetLength(&itemLength);
cellNodeList->GetLength(&cellLength);
PRInt32 rowIndex = -1;
PRInt32 cellIndex = 0;
if (cellLength != 0 && itemLength == 0) {
nsCOMPtr<nsIDOMNode> node;
cellNodeList->Item(0, getter_AddRefs(node));
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
treeRowGroup->IndexOfCell(aPresContext, content, rowIndex, cellIndex);
}
else if (cellLength == 0 && itemLength != 0) {
nsCOMPtr<nsIDOMNode> node;
itemNodeList->Item(0, getter_AddRefs(node));
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
treeRowGroup->IndexOfRow(aPresContext, content, rowIndex);
}
else if (cellLength != 0 && itemLength != 0) {
nsCOMPtr<nsIDOMNode> node;
cellNodeList->Item(0, getter_AddRefs(node));
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
treeRowGroup->IndexOfCell(aPresContext, content, rowIndex, cellIndex);
}
// We now have a valid row and cell index for the current selection. Based on the
// direction, let's adjust the row and column index.
if (rowIndex == -1)
rowIndex = 0;
else if (keyCode == NS_VK_DOWN)
rowIndex++;
else if (keyCode == NS_VK_UP)
rowIndex--;
// Ensure that the required index is visible.
treeRowGroup->EnsureRowIsVisible(rowIndex);
// now that it's (probably) been brought into view, is it valid?
// if (!treeRowGroup->IsValidRow(rowIndex))
// return NS_OK;
// Now that the row is scrolled into view, we have a frame created. We can retrieve the cell.
nsTreeCellFrame* cellFrame=nsnull;
treeRowGroup->GetCellFrameAtIndex(rowIndex, cellIndex, &cellFrame);
if (!cellFrame)
return NS_OK; // No cell. Whatever. Bail.
// We got it! Perform the selection on an up/down.
if (keyCode == NS_VK_UP || keyCode == NS_VK_DOWN)
SetSelection(aPresContext, cellFrame);
else if (keyCode == NS_VK_ENTER || keyCode == NS_VK_RETURN)
cellFrame->ToggleOpenClose();
else if (keyCode == NS_VK_LEFT)
cellFrame->Close();
else if (keyCode == NS_VK_RIGHT)
cellFrame->Open();
}
}
return NS_OK;
}
void nsTreeFrame::MoveUp(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame)
{
PRInt32 rowIndex;
pFrame->GetRowIndex(rowIndex);
PRInt32 colIndex;
pFrame->GetColIndex(colIndex);
if (rowIndex > 0)
{
MoveToRowCol(aPresContext, rowIndex-1, colIndex);
}
}
void nsTreeFrame::MoveDown(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame)
{
PRInt32 rowIndex;
pFrame->GetRowIndex(rowIndex);
PRInt32 colIndex;
pFrame->GetColIndex(colIndex);
PRInt32 totalRows = mCellMap->GetRowCount();
if (rowIndex < totalRows-1)
{
MoveToRowCol(aPresContext, rowIndex+1, colIndex);
}
}
void nsTreeFrame::MoveLeft(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame)
{
PRInt32 rowIndex;
pFrame->GetRowIndex(rowIndex);
PRInt32 colIndex;
pFrame->GetColIndex(colIndex);
if (colIndex > 0)
{
MoveToRowCol(aPresContext, rowIndex, colIndex-1);
}
}
void nsTreeFrame::MoveRight(nsIPresContext& aPresContext, nsTreeCellFrame* aFrame)
{
PRInt32 rowIndex;
aFrame->GetRowIndex(rowIndex);
PRInt32 colIndex;
aFrame->GetColIndex(colIndex);
PRInt32 totalCols = mCellMap->GetColCount();
if (colIndex < totalCols-1)
{
MoveToRowCol(aPresContext, rowIndex, colIndex+1);
}
}
void nsTreeFrame::MoveToRowCol(nsIPresContext& aPresContext, PRInt32 aRow, PRInt32 aCol)
{
nsTableCellFrame* cellFrame = mCellMap->GetCellInfoAt(aRow, aCol);
// We now have the cell that should be selected.
nsTreeCellFrame* treeCell = NS_STATIC_CAST(nsTreeCellFrame*, cellFrame);
SetSelection(aPresContext, treeCell);
}
NS_IMETHODIMP
nsTreeFrame::Destroy(nsIPresContext& aPresContext)
{
nsCOMPtr<nsIDOMEventReceiver> target = do_QueryInterface(mContent);
target->RemoveEventListener("mousedown", mTwistyListener, PR_TRUE);
mTwistyListener = nsnull;
return nsTableFrame::Destroy(aPresContext);
}
NS_IMETHODIMP
nsTreeFrame::Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = NS_OK;
mSlatedForReflow = PR_FALSE;
if (!mSuppressReflow) {
nsRect rect;
GetRect(rect);
if (rect.width != aReflowState.mComputedWidth && aReflowState.reason == eReflowReason_Resize) {
// We're doing a resize and changing the width of the table. All rows must
// reflow. Reset our generation.
SetUseGeneration(PR_FALSE);
}
if (UseGeneration()) {
++mGeneration;
}
rv = nsTableFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
}
else
{
aStatus = NS_FRAME_COMPLETE;
}
if (aReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE)
aDesiredSize.width = aReflowState.mComputedWidth +
aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right;
if (aReflowState.mComputedHeight != NS_UNCONSTRAINEDSIZE)
aDesiredSize.height = aReflowState.mComputedHeight +
aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom;
aDesiredSize.ascent = aDesiredSize.height;
if (!UseGeneration())
SetUseGeneration(PR_TRUE);
return rv;
}
NS_IMETHODIMP
nsTreeFrame::DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus)
{
nsresult rv = nsTableFrame::DidReflow(aPresContext, aStatus);
return rv;
}
NS_IMETHODIMP
nsTreeFrame::MarkForDirtyReflow(nsIPresContext& aPresContext)
{
mSuppressReflow = PR_FALSE;
InvalidateCellMap();
InvalidateColumnCache();
InvalidateFirstPassCache();
nsCOMPtr<nsIPresShell> shell;
aPresContext.GetShell(getter_AddRefs(shell));
nsFrameState frameState;
nsIFrame* tableParentFrame;
nsIReflowCommand* reflowCmd;
// Mark the table frame as dirty
GetFrameState(&frameState);
frameState |= NS_FRAME_IS_DIRTY;
SetFrameState(frameState);
// Target the reflow comamnd at its parent frame
GetParent(&tableParentFrame);
nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, tableParentFrame,
nsIReflowCommand::ReflowDirty);
if (NS_SUCCEEDED(rv)) {
// Add the reflow command
rv = shell->AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
return rv;
}
NS_IMETHODIMP
nsTreeFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsTableFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
// Create the menu bar listener.
mTwistyListener = new nsTreeTwistyListener();
nsCOMPtr<nsIDOMEventReceiver> target = do_QueryInterface(mContent);
target->AddEventListener("mousedown", mTwistyListener, PR_TRUE);
return rv;
}
PRBool
nsTreeFrame::ContainsFlexibleColumn(PRInt32 aStartIndex, PRInt32 aEndIndex,
nsTableColFrame** aResult)
{
for (PRInt32 i = aEndIndex; i >= aStartIndex; i--) {
nsTableColFrame* result = GetColFrame(i);
nsCOMPtr<nsIContent> colContent;
result->GetContent(getter_AddRefs(colContent));
nsCOMPtr<nsIAtom> fixedAtom = dont_AddRef(NS_NewAtom("fixed"));
if (colContent) {
nsAutoString fixedValue;
colContent->GetAttribute(kNameSpaceID_None, fixedAtom, fixedValue);
if (fixedValue != "true") {
// We are a proportional column.
if (aResult)
*aResult = result;
return PR_TRUE;
}
}
}
return PR_FALSE;
}

View File

@@ -0,0 +1,91 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsTableFrame.h"
#include "nsVoidArray.h"
class nsTreeCellFrame;
class nsTreeRowGroupFrame;
class nsTreeTwistyListener;
class nsTreeFrame : public nsTableFrame
{
public:
friend nsresult NS_NewTreeFrame(nsIFrame** aNewFrame);
void SetSelection(nsIPresContext& presContext, nsTreeCellFrame* pFrame);
void ToggleSelection(nsIPresContext& presContext, nsTreeCellFrame* pFrame);
void RangedSelection(nsIPresContext& aPresContext, nsTreeCellFrame* pEndFrame);
void MoveUp(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame);
void MoveDown(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame);
void MoveLeft(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame);
void MoveRight(nsIPresContext& aPresContext, nsTreeCellFrame* pFrame);
void MoveToRowCol(nsIPresContext& aPresContext, PRInt32 row, PRInt32 col);
PRBool IsSlatedForReflow() { return mSlatedForReflow; };
void SlateForReflow() { mSlatedForReflow = PR_TRUE; };
void GetTreeBody(nsTreeRowGroupFrame** aResult);
// Overridden methods
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
PRBool RowGroupsShouldBeConstrained() { return PR_TRUE; }
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aMetrics,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
nsDidReflowStatus aStatus);
PRInt32 GetCurrentGeneration() { return mGeneration; };
void SetCurrentGeneration(PRInt32 aGeneration) { mGeneration = aGeneration; };
PRBool UseGeneration() { return mUseGeneration; };
void SetUseGeneration(PRBool aUse) { mUseGeneration = aUse; };
PRBool ContainsFlexibleColumn(PRInt32 aStartIndex, PRInt32 aEndIndex, nsTableColFrame** aResult);
NS_IMETHOD MarkForDirtyReflow(nsIPresContext& aPresContext);
void SuppressReflow() { mSuppressReflow = PR_TRUE; };
void UnsuppressReflow() { mSuppressReflow = PR_FALSE; };
protected:
nsTreeFrame();
virtual ~nsTreeFrame();
protected: // Data Members
PRBool mSlatedForReflow; // If set, don't waste time scheduling excess reflows.
nsTreeTwistyListener* mTwistyListener;
PRInt32 mGeneration;
PRBool mUseGeneration;
PRBool mSuppressReflow;
}; // class nsTreeFrame

View File

@@ -0,0 +1,128 @@
/* -*- Mode: C++; tab-width: 2; 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.
*/
#include "nsFrame.h"
#include "nsLineLayout.h"
#include "nsHTMLIIDs.h"
#include "nsIPresContext.h"
#include "nsIPresShell.h"
#include "nsXULAtoms.h"
#include "nsUnitConversion.h"
#include "nsIStyleContext.h"
#include "nsIContent.h"
#include "nsStyleConsts.h"
#include "nsINameSpaceManager.h"
#include "nsTreeIndentationFrame.h"
#include "nsCOMPtr.h"
nsTreeIndentationFrame::nsTreeIndentationFrame()
{
mWidth = 0;
mHaveComputedWidth = PR_FALSE;
}
nsresult
NS_NewTreeIndentationFrame(nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsTreeIndentationFrame* it = new nsTreeIndentationFrame();
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
*aNewFrame = it;
return NS_OK;
}
nsTreeIndentationFrame::~nsTreeIndentationFrame()
{
}
NS_IMETHODIMP
nsTreeIndentationFrame::Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aMetrics,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
aStatus = NS_FRAME_COMPLETE;
// By default, we have no area
aMetrics.width = 0;
aMetrics.height = 0;
aMetrics.ascent = 0;
aMetrics.descent = 0;
// Compute our width based on the depth of our node within the content model
if (!mHaveComputedWidth)
{
mWidth = 0;
nscoord level = 0;
// First climb out to the tree item level.
nsIFrame* aFrame = this;
nsCOMPtr<nsIContent> pContent;
aFrame->GetContent(getter_AddRefs(pContent));
nsCOMPtr<nsIAtom> pTag;
pContent->GetTag(*getter_AddRefs(pTag));
if (pTag)
{
while (aFrame && pTag && pTag.get() != nsXULAtoms::treeitem)
{
aFrame->GetParent(&aFrame);
// nsCOMPtr correctly handles releasing the old |pContent| and |pTag|
aFrame->GetContent(getter_AddRefs(pContent));
pContent->GetTag(*getter_AddRefs(pTag));
}
// We now have a tree row content node. Start counting our level of nesting.
nsCOMPtr<nsIContent> pParentContent;
while (pTag.get() != nsXULAtoms::tree && pTag.get() != nsXULAtoms::treehead)
{
pContent->GetParent(*getter_AddRefs(pParentContent));
pParentContent->GetTag(*getter_AddRefs(pTag));
pContent = pParentContent;
++level;
}
level = (level/2) - 1;
if (level < 0) level = 0;
mWidth = level*16; // Hardcode an indentation of 16 pixels for now. TODO: Make this a parameter or something
}
}
float p2t;
aPresContext.GetScaledPixelsToTwips(&p2t);
if (0 != mWidth) {
aMetrics.width = NSIntPixelsToTwips(mWidth, p2t);
}
if (nsnull != aMetrics.maxElementSize) {
aMetrics.maxElementSize->width = aMetrics.width;
aMetrics.maxElementSize->height = aMetrics.height;
}
return NS_OK;
}

View File

@@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
class nsTreeIndentationFrame : public nsFrame {
public:
friend nsresult NS_NewTreeIndentationFrame(nsIFrame** aNewFrame);
// nsIHTMLReflow
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
nsTreeIndentationFrame();
protected:
virtual ~nsTreeIndentationFrame();
nscoord mWidth;
PRBool mHaveComputedWidth;
};

View File

@@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsCOMPtr.h"
#include "nsTreeOuterFrame.h"
#include "nsIStyleContext.h"
#include "nsIContent.h"
#include "nsCSSRendering.h"
#include "nsTreeCellFrame.h"
#include "nsCellMap.h"
#include "nsIDOMXULTreeElement.h"
#include "nsINameSpaceManager.h"
#include "nsXULAtoms.h"
//
// NS_NewTreeOuterFrame
//
// Creates a new tree frame
//
nsresult
NS_NewTreeOuterFrame (nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsTreeOuterFrame* it = new nsTreeOuterFrame;
if (!it)
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
} // NS_NewTreeOuterFrame
// Constructor
nsTreeOuterFrame::nsTreeOuterFrame()
:nsTableOuterFrame() { }
// Destructor
nsTreeOuterFrame::~nsTreeOuterFrame()
{
}
NS_IMETHODIMP
nsTreeOuterFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
aEventStatus = nsEventStatus_eConsumeDoDefault;
if (aEvent->message == NS_KEY_DOWN) {
// Retrieve the tree frame.
nsIFrame* curr = mFrames.FirstChild();
while (curr) {
nsCOMPtr<nsIContent> content;
curr->GetContent(getter_AddRefs(content));
if (content) {
nsCOMPtr<nsIAtom> tag;
content->GetTag(*getter_AddRefs(tag));
if (tag && tag.get() == nsXULAtoms::tree) {
// This is our actual tree frame.
return curr->HandleEvent(aPresContext, aEvent, aEventStatus);
}
}
curr->GetNextSibling(&curr);
}
}
return NS_OK;
}

View File

@@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsTableOuterFrame.h"
class nsTreeOuterFrame : public nsTableOuterFrame
{
public:
friend nsresult NS_NewTreeOuterFrame(nsIFrame** aNewFrame);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
protected:
nsTreeOuterFrame();
virtual ~nsTreeOuterFrame();
protected: // Data Members
}; // class nsTreeOuterFrame

View File

@@ -0,0 +1,405 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsCOMPtr.h"
#include "nsTreeFrame.h"
#include "nsTreeRowFrame.h"
#include "nsIStyleContext.h"
#include "nsIContent.h"
#include "nsCSSRendering.h"
#include "nsTreeCellFrame.h"
#include "nsCellMap.h"
#include "nsIDOMXULTreeElement.h"
#include "nsINameSpaceManager.h"
#include "nsTreeRowGroupFrame.h"
#include "nsXULAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsTableColFrame.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXULTreeElement.h"
#include "nsTreeTwistyListener.h"
#include "nsIViewManager.h"
#include "nsIView.h"
#include "nsIPresContext.h"
//
// NS_NewTreeFrame
//
// Creates a new tree frame
//
nsresult
NS_NewTreeRowFrame (nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsTreeRowFrame* it = new nsTreeRowFrame;
if (!it)
return NS_ERROR_OUT_OF_MEMORY;
*aNewFrame = it;
return NS_OK;
} // NS_NewTreeRowFrame
// Constructor
nsTreeRowFrame::nsTreeRowFrame()
:nsTableRowFrame(), mIsHeader(PR_FALSE), mGeneration(0), mDraggingHeader(PR_FALSE),
mHitFrame(nsnull), mFlexingCol(nsnull), mHeaderPosition(0)
{ }
// Destructor
nsTreeRowFrame::~nsTreeRowFrame()
{
}
NS_METHOD nsTreeRowFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aNextFrame)
{
nsRect rect;
GetRect(rect);
nsresult rv = nsTableRowFrame::IR_TargetIsChild(aPresContext, aDesiredSize, aReflowState, aStatus, aNextFrame);
if (rv == NS_OK) {
// Find out if our height changed. With the tree widget, changing the height of a row is a
// big deal, since it may force us to dynamically isntantiate newly exposed frames.
if (rect.height != aDesiredSize.height) {
// Retrieve the table frame and invalidate the cell map.
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->InvalidateCellMap();
}
}
return rv;
}
NS_IMETHODIMP
nsTreeRowFrame::Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsTableRowFrame::Init(aPresContext, aContent, aParent, aContext,
aPrevInFlow);
// Determine if we're a column header or not.
// Get row group frame
if (aParent != nsnull)
{
// Get the display type of the row group frame and see if it's a header or body
nsCOMPtr<nsIStyleContext> parentContext;
aParent->GetStyleContext(getter_AddRefs(parentContext));
if (parentContext)
{
const nsStyleDisplay* display = (const nsStyleDisplay*)
parentContext->GetStyleData(eStyleStruct_Display);
if (display->mDisplay == NS_STYLE_DISPLAY_TABLE_HEADER_GROUP)
{
mIsHeader = PR_TRUE;
// headers get their own views, so that they can capture events
CreateViewForFrame(aPresContext,this,aContext,PR_TRUE);
nsIView* view;
GetView(&aPresContext, &view);
view->SetContentTransparency(PR_TRUE);
}
else
{
mIsHeader = PR_FALSE;
// Determine the row's generation.
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(aParent, tableFrame);
nsTreeFrame* treeFrame = (nsTreeFrame*)tableFrame;
mGeneration = treeFrame->GetCurrentGeneration();
}
}
}
return rv;
}
NS_IMETHODIMP
nsTreeRowFrame::HeaderDrag(nsIPresContext* aPresContext, PRBool aGrabMouseEvents)
{
// get its view
nsIView* view = nsnull;
GetView(aPresContext, &view);
nsCOMPtr<nsIViewManager> viewMan;
PRBool result;
if (view) {
view->GetViewManager(*getter_AddRefs(viewMan));
if (viewMan) {
if (aGrabMouseEvents) {
viewMan->GrabMouseEvents(view,result);
mDraggingHeader = PR_TRUE;
} else {
viewMan->GrabMouseEvents(nsnull,result);
mDraggingHeader = PR_FALSE;
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsTreeRowFrame::Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
/*
if (aReflowState.reason != eReflowReason_Incremental) {
// Determine the row's generation.
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
nsTreeFrame* treeFrame = (nsTreeFrame*)tableFrame;
if (treeFrame->UseGeneration()) {
PRInt32 currGeneration = treeFrame->GetCurrentGeneration();
if (currGeneration > mGeneration) {
nsRect rect;
GetRect(rect);
aDesiredSize.width = rect.width;
aDesiredSize.height = rect.height;
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
}
}
*/
/* static int i = 0;
i++;
printf("Full row reflow! Number %d\n", i);
*/
return nsTableRowFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
}
nsresult
nsTreeRowFrame::HandleMouseUpEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
if (DraggingHeader()) {
HeaderDrag(&aPresContext, PR_FALSE);
}
return NS_OK;
}
NS_IMETHODIMP
nsTreeRowFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
aEventStatus = nsEventStatus_eConsumeDoDefault;
if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
HandleMouseUpEvent(aPresContext, aEvent, aEventStatus);
else if (aEvent->message == NS_MOUSE_MOVE && mDraggingHeader && mHitFrame)
HandleHeaderDragEvent(aPresContext, aEvent, aEventStatus);
return NS_OK;
}
NS_IMETHODIMP
nsTreeRowFrame::GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint, // Overridden to capture events
nsIFrame** aFrame)
{
nsresult rv = nsTableRowFrame::GetFrameForPoint(aPresContext, aPoint, aFrame);
if (mDraggingHeader) {
mHitFrame = *aFrame;
*aFrame = this;
nsRect rect;
GetRect(rect);
if (rect.x > aPoint.x || (rect.x+rect.width < aPoint.x)) {
mHitFrame = nsnull;
}
}
return rv;
}
NS_IMETHODIMP
nsTreeRowFrame::GetCursor(nsIPresContext& aPresContext,
nsPoint& aPoint,
PRInt32& aCursor)
{
if (mDraggingHeader) {
nsRect rect;
GetRect(rect);
if (rect.x > aPoint.x || (rect.x+rect.width < aPoint.x)) {
aCursor = NS_STYLE_CURSOR_DEFAULT;
}
else {
aCursor = NS_STYLE_CURSOR_W_RESIZE;
}
}
else aCursor = NS_STYLE_CURSOR_DEFAULT;
return NS_OK;
}
nsresult
nsTreeRowFrame::HandleHeaderDragEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus)
{
// Grab our tree frame.
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame);
nsTreeFrame* treeFrame = (nsTreeFrame*)tableFrame;
// Until we finish all of our batched operations, suppress all reflow.
treeFrame->SuppressReflow();
PRInt32 columnCount = treeFrame->GetColCount();
PRInt32* colWidths = new PRInt32[columnCount];
nsCRT::memset(colWidths, 0, columnCount*sizeof(PRInt32));
// Retrieve our column widths.
PRInt32 i;
for (i = 0; i < columnCount; i++) {
nsTableColFrame* result = treeFrame->GetColFrame(i);
nsCOMPtr<nsIContent> colContent;
result->GetContent(getter_AddRefs(colContent));
nsCOMPtr<nsIAtom> fixedAtom = dont_AddRef(NS_NewAtom("fixed"));
if (colContent) {
nsAutoString fixedValue;
colContent->GetAttribute(kNameSpaceID_None, fixedAtom, fixedValue);
if (fixedValue != "true") {
// We are a proportional column and should be annotated with our current
// width.
PRInt32 colWidth = treeFrame->GetColumnWidth(i);
colWidths[i] = colWidth;
}
}
}
// Annotate with the current proportions
for (i = 0; i < columnCount; i++) {
if (colWidths[i] > 0) {
nsTableColFrame* result = treeFrame->GetColFrame(i);
nsCOMPtr<nsIContent> colContent;
result->GetContent(getter_AddRefs(colContent));
if (colContent) {
PRInt32 colWidth = colWidths[i];
char ch[100];
sprintf(ch,"%d*", colWidth);
nsAutoString propColWidth(ch);
colContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, propColWidth,
PR_TRUE);
}
}
}
// Figure out how much we shifted the mouse.
char ch[100];
nsPoint point = ((nsMouseEvent*)aEvent)->point;
PRInt32 delta = mHeaderPosition - point.x;
mHeaderPosition = point.x;
// The proportional columns to the right will gain or lose space
// according to the percentages they currently consume.
nscoord propTotal = 0;
// Find our flexing col and note its index and width.
PRInt32 colX;
PRInt32 flexWidth = 0;
PRInt32 flexIndex = 0;
for (colX = 0; colX < columnCount; colX++) {
// Get column information
nsTableColFrame* colFrame = tableFrame->GetColFrame(colX);
if (colFrame == mFlexingCol) {
flexWidth = colWidths[colX];
flexIndex = colX;
break;
}
}
for (colX = flexIndex+1; colX < columnCount; colX++) {
// Retrieve the current widths for these columns and compute
// the total amount of space they occupy.
propTotal += colWidths[colX];
}
// Iterate over the columns to the right of the flexing column,
// and give them a percentage of the delta based off their proportions.
nsCOMPtr<nsIContent> colContent;
nsTableColFrame* colFrame;
PRInt32 colWidth = 0;
PRInt32 remaining = delta;
for (colX = flexIndex+1; colX < columnCount; colX++) {
if (colWidths[colX] > 0) {
colFrame = tableFrame->GetColFrame(colX);
float percentage = ((float)colWidths[colX])/((float)propTotal);
PRInt32 mod = (PRInt32)(percentage * (float)delta);
colWidth = colWidths[colX] + mod;
sprintf(ch,"%d*", colWidth);
nsAutoString propColWidth(ch);
colFrame->GetContent(getter_AddRefs(colContent));
if (colContent) {
colContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, propColWidth,
PR_TRUE);
}
remaining -= mod;
}
}
// Fix the spillover. We'll probably be off by a little.
if (remaining != 0 && colContent) {
colWidth += remaining;
sprintf(ch,"%d*", colWidth);
nsAutoString propColWidth(ch);
colContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, propColWidth,
PR_TRUE);
}
// Delete the colWidths array.
delete []colWidths;
// Modify the flexing column by the delta.
nsCOMPtr<nsIContent> flexContent;
mFlexingCol->GetContent(getter_AddRefs(flexContent));
if (flexContent) {
treeFrame->SetUseGeneration(PR_FALSE); // Cached rows have to reflow.
treeFrame->UnsuppressReflow();
colWidth = flexWidth - delta;
sprintf(ch,"%d*", colWidth);
nsAutoString propColWidth(ch);
flexContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, propColWidth,
PR_TRUE); // NOW we send the notification that causes the reflow.
// Do a dirty table reflow.
//treeFrame->MarkForDirtyReflow(aPresContext);
}
return NS_OK;
}

View File

@@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsTableRowFrame.h"
#include "nsVoidArray.h"
class nsTreeCellFrame;
class nsTreeRowGroupFrame;
class nsTableColFrame;
class nsTreeRowFrame : public nsTableRowFrame
{
public:
friend nsresult NS_NewTreeRowFrame(nsIFrame** aNewFrame);
// Overridden methods
NS_IMETHOD IR_TargetIsChild(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aNextFrame);
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow); // Overridden to set whether we're a column header
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint, // Overridden to capture events
nsIFrame** aFrame);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleMouseUpEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleHeaderDragEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD GetCursor(nsIPresContext& aPresContext,
nsPoint& aPoint,
PRInt32& aCursor);
NS_IMETHOD HeaderDrag(nsIPresContext* aPresContext, PRBool aGrabber);
PRBool DraggingHeader() { return mDraggingHeader; };
void SetFlexingColumn(nsTableColFrame* aTableColFrame) { mFlexingCol = aTableColFrame; };
void SetHeaderPosition(PRInt32 aHeaderPos) { mHeaderPosition = aHeaderPos; };
protected:
nsTreeRowFrame();
virtual ~nsTreeRowFrame();
protected: // Data Members
PRBool mIsHeader;
PRInt32 mGeneration;
PRBool mDraggingHeader;
nsIFrame* mHitFrame;
nsTableColFrame* mFlexingCol;
PRInt32 mHeaderPosition;
}; // class nsTreeRowFrame

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,193 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsTableRowGroupFrame.h"
#include "nsVoidArray.h"
#include "nsIScrollbarListener.h"
class nsTreeFrame;
class nsCSSFrameConstructor;
class nsISupportsArray;
class nsTreeRowGroupFrame : public nsTableRowGroupFrame, public nsIScrollbarListener
{
public:
friend nsresult NS_NewTreeRowGroupFrame(nsIFrame** aNewFrame);
NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex,
nsIAtom** aListName) const;
NS_IMETHOD FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const;
void SetScrollbarFrame(nsIFrame* aFrame);
void SetFrameConstructor(nsCSSFrameConstructor* aFrameConstructor) { mFrameConstructor = aFrameConstructor; };
void SetShouldHaveScrollbar();
void CreateScrollbar(nsIPresContext& aPresContext);
void MakeLazy() { mIsLazy = PR_TRUE; };
PRBool IsLazy() { return mIsLazy; };
NS_IMETHOD TreeAppendFrames(nsIFrame* aFrameList);
NS_IMETHOD TreeInsertFrames(nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, nsIFrame** aFrame);
void PaintChildren(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
PRBool ContinueReflow(nsIPresContext& aPresContext, nscoord y, nscoord height);
PRBool IsFull() { return mIsFull; };
// Responses to changes
void OnContentAdded(nsIPresContext& aPresContext);
void OnContentInserted(nsIPresContext& aPresContext, nsIFrame* aNextSibling);
void OnContentRemoved(nsIPresContext& aPresContext, nsIFrame* aChildFrame);
virtual nsIFrame* GetFirstFrame();
virtual nsIFrame* GetLastFrame();
virtual void GetNextFrame(nsIFrame* aFrame, nsIFrame** aResult);
virtual PRBool RowsDesireExcessSpace() { return PR_FALSE; };
virtual PRBool RowGroupDesiresExcessSpace();
NS_DECL_ISUPPORTS
NS_IMETHOD PositionChanged(nsIPresContext& aPresContext, PRInt32 aOldIndex, PRInt32 aNewIndex);
NS_IMETHOD PagedUpDown();
protected:
nsTreeRowGroupFrame();
virtual ~nsTreeRowGroupFrame();
virtual PRBool RowGroupReceivesExcessSpace();
void DestroyRows(nsTableFrame* aTableFrame, nsIPresContext& aPresContext, PRInt32& rowsToLose);
void ReverseDestroyRows(nsTableFrame* aTableFrame, nsIPresContext& aPresContext, PRInt32& rowsToLose);
NS_IMETHOD ReflowBeforeRowLayout(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsReflowReason aReason);
NS_IMETHOD ReflowAfterRowLayout(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsReflowReason aReason);
NS_IMETHOD IR_TargetIsChild(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
RowGroupReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aNextFrame);
virtual nsIFrame* GetFirstFrameForReflow(nsIPresContext& aPresContext);
virtual void GetNextFrameForReflow(nsIPresContext& aPresContext, nsIFrame* aFrame, nsIFrame** aResult);
void LocateFrame(nsIFrame* aStartFrame, nsIFrame** aResult);
void SetContentChain(nsISupportsArray* aContentChain);
void InitSubContentChain(nsTreeRowGroupFrame* aRowGroupFrame);
void ConstructContentChain(nsIContent* aRowContent);
void ConstructOldContentChain(nsIPresContext& aPresContext, nsIContent* aOldRowContent);
void CreateOldContentChain(nsIPresContext& aPresContext, nsIContent* aOldRowContent, nsIContent* topOfChain);
void FindChildOfCommonContentChainAncestor(nsIContent *startContent, nsIContent **child);
PRBool IsAncestor(nsIContent *aRowContent, nsIContent *aOldRowContent, nsIContent **firstDescendant);
void FindPreviousRowContent(PRInt32& aDelta, nsIContent* aUpwardHint,
nsIContent* aDownwardHint, nsIContent** aResult);
static void FindRowContentAtIndex(PRInt32& aIndex, nsIContent* aParent,
nsIContent** aResult);
void MarkTreeAsDirty(nsIPresContext& aPresContext, nsTreeFrame* aTreeFrame);
void GetFirstRowContent(nsIContent** aRowContent);
void ComputeVisibleRowCount(PRInt32& rowCount, nsIContent* aParent);
void PostAppendRow(nsIFrame* aRowFrame, nsIPresContext& aPresContext);
public:
// Helpers that allow access to info. The tree is the primary consumer of this
// info.
// Tells you the row and index of a cell (given only the content node).
// This method is expensive.
void IndexOfCell(nsIPresContext& aPresContext, nsIContent* aCellContent,
PRInt32& aRowIndex, PRInt32& aColIndex);
// Tells you the row index of a row (given only the content node).
// This method is expensive.
void IndexOfRow(nsIPresContext& aPresContext, nsIContent* aRowContent, PRInt32& aRowIndex);
// Whether or not the row is valid. This is a cheap method, since the total row count
// is cached.
PRBool IsValidRow(PRInt32 aRowIndex);
// This method ensures that a row is onscreen. It will scroll the tree widget such
// that the row is at the top of the screen (if the row was offscreen to start with).
void EnsureRowIsVisible(PRInt32 aRowIndex);
// This method retrieves a cell at a given index. The intent of this method is that it be
// cheap. It should not cause frames to be built, so this should only be called when the
// cell is onscreen (use EnsureRowIsVisible to guarantee this).
void GetCellFrameAtIndex(PRInt32 aRowIndex, PRInt32 aColIndex, nsTreeCellFrame** aResult);
PRInt32 GetVisibleRowCount() { return mRowCount; };
#if 0
static PRInt32 ChildrenAbove(nsIContent *parent, nsIContent *item);
static PRInt32 RecursiveTagCount(nsIContent *node, nsIAtom *tag);
static nsresult FindParentWithTag(nsIContent *node, nsIAtom *tag,
nsIContent **node);
#endif
static PRBool IsTableRowGroupFrame(nsIFrame*);
static PRBool IsTableRowFrame(nsIFrame*);
protected: // Data Members
nsIFrame* mTopFrame; // The current topmost frame in the view.
nsIFrame* mBottomFrame; // The current bottom frame in the view.
nsIFrame* mLinkupFrame; // An old top frame that we're trying to link up with.
PRBool mIsLazy; // Whether or not we're a lazily instantiated beast
PRBool mIsFull; // Whether or not we have any more room.
nsIFrame* mScrollbar; // Our scrollbar.
nsFrameList mScrollbarList; // A frame list that holds our scrollbar.
PRBool mShouldHaveScrollbar; // Whether or not we could potentially have a scrollbar.
nsISupportsArray* mContentChain; // Our content chain
nsCSSFrameConstructor* mFrameConstructor; // We don't own this. (No addref/release allowed, punk.)
nscoord mRowGroupHeight; // The height of the row group.
PRInt32 mCurrentIndex; // Our current scrolled index.
PRInt32 mRowCount; // The current number of visible rows.
}; // class nsTreeRowGroupFrame

Some files were not shown because too many files have changed in this diff Show More