summaryrefslogtreecommitdiff
path: root/rt/share/html/Admin/Tools/Theme.html
diff options
context:
space:
mode:
Diffstat (limited to 'rt/share/html/Admin/Tools/Theme.html')
-rw-r--r--rt/share/html/Admin/Tools/Theme.html219
1 files changed, 139 insertions, 80 deletions
diff --git a/rt/share/html/Admin/Tools/Theme.html b/rt/share/html/Admin/Tools/Theme.html
index 83f88a98b..3a0c71b35 100644
--- a/rt/share/html/Admin/Tools/Theme.html
+++ b/rt/share/html/Admin/Tools/Theme.html
@@ -51,7 +51,7 @@
<& /Elements/Tabs &>
<& /Elements/ListActions, actions => \@results &>
-<script type="text/javascript" src="<%RT->Config->Get('WebPath')%>/NoAuth/js/farbtastic.js"></script>
+<script type="text/javascript" src="<%RT->Config->Get('WebPath')%>/static/js/farbtastic.js"></script>
<div id="simple-customize">
<div id="upload-logo">
@@ -61,26 +61,31 @@
<label for="logo-upload"><&|/l&>Upload a new logo</&>:</label>
<input type="file" name="logo-upload" id="logo-upload" /><br />
<div class="gd-support">
-% if (%gd_can) {
+% if ($valid_image_types) {
<&|/l, $valid_image_types &>Your system supports automatic color suggestions for: [_1]</&>
% } else {
<&|/l&>GD is disabled or not installed. You can upload an image, but you won't get automatic color suggestions.</&>
% }
</div>
- <input name="reset_logo" value="Reset to default RT Logo" type="submit" />
- <input type="submit" value="Upload" />
+ <input name="reset_logo" value="<&|/l&>Reset to default RT Logo</&>" type="submit" />
+ <input type="submit" value="<&|/l&>Upload</&>" />
</form>
</div>
<div id="customize-theme">
- <h2>Customize the RT theme</h2>
+ <h2><&|/l&>Customize the RT theme</&></h2>
<ol>
<li>
<label for="section"><&|/l&>Select a section</&>:</label>
<select id="section"></select>
</li>
<li>
- <div class="description"><&|/l&>Select a color for the section</&>:</div>
+ <div class="description">
+ <&|/l&>Select a color for the section</&>:
+ <div id="logo-picker-hint" style="display: none;">
+ <&|/l&>You can also click on the logo above to get colors!</&>
+ </div>
+ </div>
% if ($colors) {
<div class="primary-colors">
% for (@$colors) {
@@ -93,27 +98,29 @@
</div>
% }
<div id="color-picker"></div>
+ <canvas id="logo-color-picker" title="<&|/l&>Click to choose a color</&>"></canvas>
</li>
</ol>
</div>
</div>
<div id="custom-css">
- <h2>Custom CSS (Advanced)</h2>
-
+ <h2><&|/l&>Custom CSS (Advanced)</&></h2>
+
<form method="POST">
<textarea rows=20 id="user_css" name="user_css" wrap="off"><% $user_css %></textarea><br />
- <input id="try" type="button" class="button" value="Try" />
- <input id="reset" type="reset" value="Reset" type="submit" />
- <input name="reset_css" value="Reset to default RT Theme" type="submit" />
- <input value="Save" type="submit" />
+ <input id="try" type="button" class="button" value="<&|/l&>Try</&>" />
+ <input id="reset" type="reset" value="<&|/l&>Reset</&>" type="submit" />
+ <input name="reset_css" value="<&|/l&>Reset to default RT Theme</&>" type="submit" />
+ <input value="<&|/l&>Save</&>" type="submit" />
</form>
</div>
<%ONCE>
my @sections = (
- ['Page' => ['body']],
- ['Header' => ['div#quickbar', 'body.aileron #main-navigation #app-nav > li, body.aileron #main-navigation #app-nav > li > a, #prefs-menu > li, #prefs-menu > li > a, #logo .rtname']],
+ ['Page' => ['body', 'div#body']],
+ ['Menu bar' => ['div#quickbar', '#main-navigation #app-nav.sf-shadow > li, #main-navigation #app-nav.sf-shadow > li > a, #prefs-menu > li, #prefs-menu > li > a, #logo .rtname']],
+ ['Title bar' => ['div#header']],
['Page title' => ['div#header h1']],
['Page content' => ['div#body']],
['Buttons' => ['input[type="reset"], input[type="submit"], input[class="button"]']],
@@ -173,7 +180,7 @@ jQuery(function($) {
newcss += "; border: none;"
/* Page title's text color is the selected color */
- if (applying[name].match(/#header/))
+ if (applying[name].match(/h1/))
newcss = "color: " + bg;
/* Nav doesn't need a background, but it wants text color */
@@ -193,7 +200,35 @@ jQuery(function($) {
change_color($(this).css('background-color'), $(this).css('color'));
});
-
+ // Setup the canvas color picker
+ $("#logo-theme-editor img").load(function() {
+ var logo = $(this);
+ var canvas = $("#logo-color-picker");
+ var el_canvas = canvas.get(0);
+
+ if (!el_canvas.getContext) return;
+
+ var context = el_canvas.getContext("2d");
+ el_canvas.width = logo.width();
+ el_canvas.height = logo.height();
+ context.drawImage(logo.get(0), 0, 0);
+
+ logo.hide().after(canvas);
+ canvas.show().click(function(ev) {
+ ev.preventDefault();
+ var R = 0,
+ G = 1,
+ B = 2,
+ A = 3;
+ var pixel = this.getContext("2d").getImageData(ev.offsetX, ev.offsetY, 1, 1).data;
+ // Farbtastic expects values in the range of 0..1
+ var rgba = $.makeArray(pixel).map(function(v,i) { return v / 255 });
+ var wheel = $.farbtastic("#color-picker");
+ wheel.setHSL( wheel.RGBToHSL( rgba.slice(R,A) ) );
+ // XXX TODO factor in the alpha channel too
+ });
+ $('#logo-picker-hint').show();
+ });
});
</script>
<%INIT>
@@ -207,14 +242,82 @@ my $text_threshold = 0.6;
my @results;
my $imgdata;
+my $colors;
+my $valid_image_types;
+if (not RT->Config->Get('DisableGD') and Convert::Color->require) {
+ require GD;
+
+ # Always find out what GD can read...
+ my %gd_can;
+ for my $type (qw(Png Jpeg Gif)) {
+ $gd_can{$type}++ if GD::Image->can("newFrom${type}Data");
+ }
+ $valid_image_types = join(", ", map { uc } sort { lc $a cmp lc $b } keys %gd_can);
+}
+
+my $analyze_img = sub {
+ return undef unless $valid_image_types;
+
+ my $imgdata = shift;
+ return undef unless $imgdata;
+
+ # ...but only analyze the image if we have data
+ my $img = GD::Image->new($imgdata);
+ unless ($img) {
+ # This has to be one damn long line because the loc() needs to be
+ # source parsed correctly.
+ push @results, loc("Automatically suggested theme colors aren't available for your image. This might be because you uploaded an image type that your installed version of GD doesn't support. Supported types are: [_1]. You can recompile libgd and GD.pm to include support for other image types.", $valid_image_types);
+ return undef;
+ }
+
+ my %colors;
+
+ my @wsamples;
+ my @hsamples;
+ if ($img->width > 200) {
+ @wsamples = map { int($img->width*($_/200)) } (0..199);
+ } else {
+ @wsamples = ( 0 .. $img->width - 1 );
+ }
+ if ($img->height > 200) {
+ @hsamples = map { int($img->height*($_/200)) } (0..199);
+ } else {
+ @hsamples = ( 0 .. $img->height - 1 );
+ }
+ for my $i (@wsamples) {
+ for my $j (@hsamples) {
+ my @color = $img->rgb( $img->getPixel($i,$j) );
+ my $hsl = Convert::Color->new('rgb:'.join(',',map { $_ / 255 } @color))->convert_to('hsl');
+ my $c = join(',',@color);
+ next if $hsl->lightness < 0.1;
+ $colors{$c} ||= { h => $hsl->hue, s => $hsl->saturation, l => $hsl->lightness, cnt => 0, c => $c};
+ $colors{$c}->{cnt}++;
+ }
+ }
+
+ for (values %colors) {
+ $_->{rank} = $_->{s} * $_->{cnt};
+ }
+ my @top5 = grep { defined and $_->{'l'} and $_->{'c'} }
+ (sort { $b->{rank} <=> $a->{rank} } values %colors)[0..5];
+ return \@top5;
+};
+
if (my $file_hash = _UploadedFile( 'logo-upload' )) {
- my ($id, $msg) = RT->System->SetAttribute( Name => "UserLogo",
- Description => "User-provided logo",
- Content => {
- type => $file_hash->{ContentType},
- data => $file_hash->{LargeContent},
- hash => md5_hex($file_hash->{LargeContent}),
- } );
+ $colors = $analyze_img->($file_hash->{LargeContent});
+
+ my $my_system = RT::System->new( $session{CurrentUser} );
+ my ( $id, $msg ) = $my_system->SetAttribute(
+ Name => "UserLogo",
+ Description => "User-provided logo",
+ Content => {
+ type => $file_hash->{ContentType},
+ data => $file_hash->{LargeContent},
+ hash => md5_hex($file_hash->{LargeContent}),
+ colors => $colors,
+ },
+ );
+
push @results, loc("Unable to set UserLogo: [_1]", $msg) unless $id;
$imgdata = $file_hash->{LargeContent};
@@ -227,6 +330,19 @@ else {
my $content = $attr->Content;
if (ref($content) eq 'HASH') {
$imgdata = $content->{data};
+ $colors = $content->{colors};
+ unless ($colors) {
+ # No colors cached; attempt to generate them
+ $colors = $content->{colors} = $analyze_img->($content->{data});
+ if ($content->{colors}) {
+ # Found colors; update the attribute
+ RT->System->SetAttribute(
+ Name => "UserLogo",
+ Description => "User-provided logo",
+ Content => $content,
+ );
+ }
+ }
}
else {
RT->System->DeleteAttribute('UserLogo');
@@ -256,63 +372,6 @@ if (!$user_css) {
} @sections
);
}
-
-# XXX: move this to some other modules
-
-use List::MoreUtils qw(uniq);
-
-my $has_color_analyzer = eval { require Convert::Color; 1 };
-my $colors;
-my %gd_can;
-my $valid_image_types;
-
-if (not RT->Config->Get('DisableGD') and $has_color_analyzer) {
- require GD;
-
- # Always find out what GD can read...
- for my $type (qw(Png Jpeg Gif)) {
- $gd_can{$type}++ if GD::Image->can("newFrom${type}Data");
- }
- $valid_image_types = join(", ", map { uc } sort { lc $a cmp lc $b } keys %gd_can);
-
- # ...but only analyze the image if we have data
- if ($imgdata) {
- if ( my $img = GD::Image->new($imgdata) ) {
- $colors = analyze_img($img);
- }
- else {
- # This has to be one damn long line because the loc() needs to be
- # source parsed correctly.
- push @results, loc("Automatically suggested theme colors aren't available for your image. This might be because you uploaded an image type that your installed version of GD doesn't support. Supported types are: [_1]. You can recompile libgd and GD.pm to include support for other image types.", $valid_image_types);
- }
- }
-}
-
-sub analyze_img {
- my $img = shift;
- my $color;
-
- for my $i (0..$img->width-1) {
- for my $j (0..$img->height-1) {
- my @color = $img->rgb( $img->getPixel($i,$j) );
- my $hsl = Convert::Color->new('rgb:'.join(',',map { $_ / 255 } @color))->convert_to('hsl');
- my $c = join(',',@color);
- next if $hsl->lightness < 0.1;
- $color->{$c} ||= { h => $hsl->hue, s => $hsl->saturation, l => $hsl->lightness, cnt => 0, c => $c};
- $color->{$c}->{cnt}++;
- }
- }
-
- for (values %$color) {
- $_->{rank} = $_->{s} * $_->{cnt};
- }
- my @top5 = grep { defined and $_->{'l'} and $_->{'c'} }
- (sort { $b->{rank} <=> $a->{rank} } values %$color)[0..5];
- if ((scalar uniq map {$_->{rank}} @top5) == 1) {
- $RT::Logger->info("Only one color found in logo image");
- }
- return \@top5;
-}
</%INIT>
<%ARGS>
$user_css => ''