summaryrefslogtreecommitdiff
path: root/src/renderers/pieRenderer.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderers/pieRenderer.vala')
-rw-r--r--src/renderers/pieRenderer.vala768
1 files changed, 656 insertions, 112 deletions
diff --git a/src/renderers/pieRenderer.vala b/src/renderers/pieRenderer.vala
index 8085758..2edee09 100644
--- a/src/renderers/pieRenderer.vala
+++ b/src/renderers/pieRenderer.vala
@@ -1,19 +1,19 @@
-/*
-Copyright (c) 2011 by Simon Schneegans
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the Free
-Software Foundation, either version 3 of the License, or (at your option)
-any later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-more details.
-
-You should have received a copy of the GNU General Public License along with
-this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+/////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2011-2015 by Simon Schneegans
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or (at
+// your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////
using GLib.Math;
@@ -49,13 +49,89 @@ public class PieRenderer : GLib.Object {
/// The width and height of the Pie in pixels.
/////////////////////////////////////////////////////////////////////
- public int size { get; private set; }
+ public int size_w { get; private set; }
+ public int size_h { get; private set; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Center position relative to window top-left corner
+ /////////////////////////////////////////////////////////////////////
+
+ public int center_x { get; private set; }
+ public int center_y { get; private set; }
+
+ ////////////////////////////////////////////////////////////////////
+ /// Possible show pie modes.
+ /// FULL_PIE: Show the pie as a complete circle.
+ /// HPIE_LEFT: Eat half pie so it can be shown at the left of the screen.
+ /// HPIE_RIGHT: Eat half pie so it can be shown at the right of the screen.
+ /// HPIE_TOP: Eat half pie so it can be shown at the top of the screen.
+ /// HPIE_BOTTOM: Eat half pie so it can be shown at the bottom of the screen.
+ /// CPIE_TOP_LEFT: Eat 3/4 pie so it can be shown at the top-left corner.
+ /// CPIE_TOP_RIGHT: Eat 3/4 pie so it can be shown at the top-right corner.
+ /// CPIE_BOT_LEFT: Eat 3/4 pie so it can be shown at the bottom-left corner.
+ /// CPIE_BOT_RIGHT: Eat 3/4 pie so it can be shown at the bottom-right corner.
/////////////////////////////////////////////////////////////////////
- /// True if the pie should close when it's trigger is released.
+
+ public enum ShowPieMode {
+ FULL_PIE,
+ HPIE_LEFT, HPIE_RIGHT, HPIE_TOP, HPIE_BOTTOM,
+ CPIE_TOP_LEFT, CPIE_TOP_RIGHT, CPIE_BOT_LEFT, CPIE_BOT_RIGHT}
+
/////////////////////////////////////////////////////////////////////
+ /// Show pie mode: full, half-circle, corner
+ /////////////////////////////////////////////////////////////////////
+
+ public ShowPieMode pie_show_mode { get; private set; default= ShowPieMode.FULL_PIE; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Number of visible slices
+ /////////////////////////////////////////////////////////////////////
+
+ public int visible_slice_count { get; private set; }
- public bool turbo_mode { get; private set; default=false; }
+ public int original_visible_slice_count { get; private set; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Number of slices in full pie (visible or not)
+ /////////////////////////////////////////////////////////////////////
+
+ public int total_slice_count { get; private set; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Maximun number of visible slices in a full pie
+ /////////////////////////////////////////////////////////////////////
+
+ public int max_visible_slices { get; private set; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// The index of the first visible slice
+ /////////////////////////////////////////////////////////////////////
+
+ public int first_slice_idx { get; private set; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Angular position of the first visible slice
+ /////////////////////////////////////////////////////////////////////
+
+ public double first_slice_angle { get; private set; }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Index of the slice where to go when up/down/left/right key is pressed
+ /// or -1 if that side of the pie was eaten
+ /////////////////////////////////////////////////////////////////////
+
+ public int up_slice_idx { get; private set; }
+ public int down_slice_idx { get; private set; }
+ public int left_slice_idx { get; private set; }
+ public int right_slice_idx { get; private set; }
+
+
+ /////////////////////////////////////////////////////////////////////
+ /// The ID of the currently loaded Pie.
+ /////////////////////////////////////////////////////////////////////
+
+ public string id { get; private set; }
/////////////////////////////////////////////////////////////////////
/// True if the pie is currently navigated with the keyboard. This is
@@ -77,6 +153,11 @@ public class PieRenderer : GLib.Object {
private CenterRenderer center;
/////////////////////////////////////////////////////////////////////
+ /// Maximum distance from the center that activates the slices
+ /////////////////////////////////////////////////////////////////////
+ private int activation_range;
+
+ /////////////////////////////////////////////////////////////////////
/// C'tor, initializes members.
/////////////////////////////////////////////////////////////////////
@@ -85,7 +166,35 @@ public class PieRenderer : GLib.Object {
this.center = new CenterRenderer(this);
this.quickaction = -1;
this.active_slice = -2;
- this.size = 0;
+ this.size_w = 0;
+ this.size_h = 0;
+ this.activation_range= 300;
+
+ this.max_visible_slices= Config.global.max_visible_slices;
+
+ set_show_mode(ShowPieMode.FULL_PIE);
+ }
+
+
+ private void get_mouse_and_screen(out int mousex, out int mousey, out int screenx, out int screeny) {
+ // get the mouse position and screen resolution
+ double x = 0.0;
+ double y = 0.0;
+
+ var display = Gdk.Display.get_default();
+ var manager = display.get_device_manager();
+ GLib.List<weak Gdk.Device?> list = manager.list_devices(Gdk.DeviceType.MASTER);
+
+ foreach(var device in list) {
+ if (device.input_source != Gdk.InputSource.KEYBOARD) {
+ Gdk.Screen screen;
+ device.get_position( out screen, out x, out y );
+ }
+ }
+ mousex= (int) x;
+ mousey= (int) y;
+ screenx= Gdk.Screen.width();
+ screeny= Gdk.Screen.height();
}
/////////////////////////////////////////////////////////////////////
@@ -95,6 +204,8 @@ public class PieRenderer : GLib.Object {
public void load_pie(Pie pie) {
this.slices.clear();
+ this.id = pie.id;
+
int count = 0;
foreach (var group in pie.action_groups) {
foreach (var action in group.actions) {
@@ -110,18 +221,200 @@ public class PieRenderer : GLib.Object {
}
}
- this.turbo_mode = PieManager.get_is_turbo(pie.id);
-
this.set_highlighted_slice(this.quickaction);
- this.size = (int)fmax(2*Config.global.theme.radius + 2*Config.global.theme.slice_radius*Config.global.theme.max_zoom,
- 2*Config.global.theme.center_radius);
+ ShowPieMode showpie= ShowPieMode.FULL_PIE;
+ //set full pie to determine the number of visible slices
+ set_show_mode(showpie);
+
+ int sz0= (int)fmax(2*Config.global.theme.radius + 2*Config.global.theme.visible_slice_radius*Config.global.theme.max_zoom,
+ 2*Config.global.theme.center_radius);
+
+ int sz= sz0;
// increase size if there are many slices
- if (slices.size > 0) {
- this.size = (int)fmax(this.size,
- (((Config.global.theme.slice_radius + Config.global.theme.slice_gap)/tan(PI/slices.size))
- + Config.global.theme.slice_radius)*2*Config.global.theme.max_zoom);
+ if (this.total_slice_count > 0) {
+ sz = (int)fmax(sz0,
+ (((Config.global.theme.slice_radius + Config.global.theme.slice_gap)/tan(PI/this.total_slice_count))
+ + Config.global.theme.visible_slice_radius)*2*Config.global.theme.max_zoom);
+ }
+
+
+
+
+ // get mouse position and screen resolution
+ int mouse_x, mouse_y, screen_x, screen_y;
+ get_mouse_and_screen( out mouse_x, out mouse_y, out screen_x, out screen_y );
+
+ //reduce the window size if needed to get closer to the actual mouse position
+ int reduce_szx= 1;
+ int reduce_szy= 1;
+
+ if (PieManager.get_is_auto_shape(pie.id) && !PieManager.get_is_centered(pie.id)) {
+ //set the best show mode that put the mouse near the center
+ if (mouse_x < sz/2) {
+ if (mouse_y < sz/2)
+ showpie= ShowPieMode.CPIE_TOP_LEFT; //show 1/4 pie
+ else if (screen_y > 0 && screen_y-mouse_y < sz/2)
+ showpie= ShowPieMode.CPIE_BOT_LEFT; //show 1/4 pie
+ else
+ showpie= ShowPieMode.HPIE_LEFT; //show 1/2 pie
+
+ } else if (mouse_y < sz/2) {
+ if (screen_x > 0 && screen_x-mouse_x < sz/2)
+ showpie= ShowPieMode.CPIE_TOP_RIGHT; //show 1/4 pie
+ else
+ showpie= ShowPieMode.HPIE_TOP; //show 1/2 pie
+
+ } else if (screen_x > 0 && screen_x-mouse_x < sz/2) {
+ if (screen_y > 0 && screen_y-mouse_y < sz/2)
+ showpie= ShowPieMode.CPIE_BOT_RIGHT; //show 1/4 pie
+ else
+ showpie= ShowPieMode.HPIE_RIGHT; //show 1/2 pie
+
+ } else if (screen_y > 0 && screen_y-mouse_y < sz/2)
+ showpie= ShowPieMode.HPIE_BOTTOM; //show 1/2 pie
+
+
+ } else {
+ //if the pie is centered in the screen, don't reduce the size
+ if (PieManager.get_is_centered(pie.id)) {
+ reduce_szx= 0;
+ reduce_szy= 0;
+ }
+
+ //select the configured shape
+ //convert from radio-buttum number to ShowPieMode enum
+ switch( PieManager.get_shape_number(pie.id) ) {
+ case 1:
+ showpie= ShowPieMode.CPIE_BOT_RIGHT;
+ if (screen_x-mouse_x > sz/2)
+ reduce_szx= 0; //keep full width
+ if (screen_y-mouse_y > sz/2)
+ reduce_szy= 0; //keep full height
+ break;
+ case 2:
+ showpie= ShowPieMode.HPIE_RIGHT;
+ if (screen_x-mouse_x > sz/2)
+ reduce_szx= 0; //keep full width
+ break;
+ case 3:
+ showpie= ShowPieMode.CPIE_TOP_RIGHT;
+ if (screen_x-mouse_x > sz/2)
+ reduce_szx= 0; //keep full width
+ if (mouse_y > sz/2)
+ reduce_szy= 0; //keep full height
+ break;
+ case 4:
+ showpie= ShowPieMode.HPIE_BOTTOM;
+ if (screen_y-mouse_y > sz/2)
+ reduce_szy= 0; //keep full height
+ break;
+ case 6:
+ showpie= ShowPieMode.HPIE_TOP;
+ if (mouse_y > sz/2)
+ reduce_szy= 0; //keep full height
+ break;
+ case 7:
+ showpie= ShowPieMode.CPIE_BOT_LEFT;
+ if (mouse_x > sz/2)
+ reduce_szx= 0; //keep full width
+ if (screen_y-mouse_y > sz/2)
+ reduce_szy= 0; //keep full height
+ break;
+ case 8:
+ showpie= ShowPieMode.HPIE_LEFT;
+ if (mouse_x > sz/2)
+ reduce_szx= 0; //keep full width
+ break;
+ case 9:
+ showpie= ShowPieMode.CPIE_TOP_LEFT;
+ if (mouse_x > sz/2)
+ reduce_szx= 0; //keep full width
+ if (mouse_y > sz/2)
+ reduce_szy= 0; //keep full height
+ break;
+ }
+ }
+ //set the new show pie mode
+ set_show_mode(showpie);
+
+ //recalc size
+ sz = sz0;
+ if (this.total_slice_count > 0) {
+ sz = (int)fmax(sz0,
+ (((Config.global.theme.slice_radius + Config.global.theme.slice_gap)/tan(PI/this.total_slice_count))
+ + Config.global.theme.visible_slice_radius)*2*Config.global.theme.max_zoom);
+ }
+ //activation_range = normal pie radius + "outer" activation_range
+ this.activation_range= (int)((double)Config.global.activation_range + sz/(2*Config.global.theme.max_zoom));
+
+ int szx = 1; //full width
+ int szy = 1; //full height
+ switch(this.pie_show_mode) {
+ //half pie
+ case ShowPieMode.HPIE_LEFT:
+ szx = 0; //half width, center to the left
+ break;
+ case ShowPieMode.HPIE_RIGHT:
+ szx = 2; //half width, center to the right
+ break;
+ case ShowPieMode.HPIE_TOP:
+ szy = 0; //half height, center to the top
+ break;
+ case ShowPieMode.HPIE_BOTTOM:
+ szy = 2; //half height, center to the bottom
+ break;
+
+ //cuarter pie
+ case ShowPieMode.CPIE_TOP_LEFT:
+ szx = 0; //half width, center to the left
+ szy = 0; //half height, center to the top
+ break;
+ case ShowPieMode.CPIE_TOP_RIGHT:
+ szx = 2; //half width, center to the right
+ szy = 0; //half height, center to the top
+ break;
+ case ShowPieMode.CPIE_BOT_LEFT:
+ szx = 0; //half width, center to the left
+ szy = 2; //half height, center to the bottom
+ break;
+ case ShowPieMode.CPIE_BOT_RIGHT:
+ szx = 2; //half width, center to the right
+ szy = 2; //half height, center to the bottom
+ break;
+ }
+ if (reduce_szx == 0)
+ szx = 1; //don't reduce width
+ if (reduce_szy == 0)
+ szy = 1; //don't reduce height
+
+ int rc = (int)Config.global.theme.center_radius;
+ if (szx == 1 ) {
+ //full width
+ this.size_w = sz;
+ this.center_x = sz/2; //center position
+ } else {
+ //half width
+ this.size_w = sz/2 + rc;
+ if (szx == 0) {
+ this.center_x = rc; //center to the left
+ } else {
+ this.center_x = this.size_w-rc; //center to the right
+ }
+ }
+ if (szy == 1) {
+ //full heigth
+ this.size_h = sz;
+ this.center_y = sz/2; //center position
+ } else {
+ //half heigth
+ this.size_h = sz/2 + rc;
+ if (szy == 0) {
+ this.center_y = rc; //center to the top
+ } else {
+ this.center_y = this.size_h-rc; //center to the bottom
+ }
}
}
@@ -130,12 +423,16 @@ public class PieRenderer : GLib.Object {
/////////////////////////////////////////////////////////////////////
public void activate() {
- if (this.active_slice >= 0 && this.active_slice < this.slices.size) {
+ if (this.active_slice >= this.first_slice_idx
+ && this.active_slice < this.first_slice_idx+this.visible_slice_count) {
slices[active_slice].activate();
}
- foreach (var slice in this.slices)
- slice.fade_out();
+ //foreach (var slice in this.slices)
+ // slice.fade_out();
+ for (int i= 0; i < this.visible_slice_count; ++i) {
+ this.slices[ i+this.first_slice_idx ].fade_out();
+ }
center.fade_out();
}
@@ -145,29 +442,23 @@ public class PieRenderer : GLib.Object {
/////////////////////////////////////////////////////////////////////
public void cancel() {
- foreach (var slice in this.slices)
- slice.fade_out();
+ //foreach (var slice in this.slices)
+ // slice.fade_out();
+ for (int i= 0; i < this.visible_slice_count; ++i) {
+ this.slices[ i+this.first_slice_idx ].fade_out();
+ }
center.fade_out();
}
+
/////////////////////////////////////////////////////////////////////
/// Called when the up-key is pressed. Selects the next slice towards
/// the top.
/////////////////////////////////////////////////////////////////////
public void select_up() {
- int bottom = this.slice_count()/4;
- int top = this.slice_count()*3/4;
-
- if (this.active_slice == -1 || this.active_slice == bottom)
- this.set_highlighted_slice(top);
- else if (this.active_slice > bottom && this.active_slice < top)
- this.set_highlighted_slice(this.active_slice+1);
- else if (this.active_slice != top)
- this.set_highlighted_slice((this.active_slice-1+this.slice_count())%this.slice_count());
-
- this.key_board_control = true;
+ move_active_slice(this.up_slice_idx, this.down_slice_idx);
}
/////////////////////////////////////////////////////////////////////
@@ -176,17 +467,7 @@ public class PieRenderer : GLib.Object {
/////////////////////////////////////////////////////////////////////
public void select_down() {
- int bottom = this.slice_count()/4;
- int top = this.slice_count()*3/4;
-
- if (this.active_slice == -1 || this.active_slice == top)
- this.set_highlighted_slice(bottom);
- else if (this.active_slice > bottom && this.active_slice < top)
- this.set_highlighted_slice(this.active_slice-1);
- else if (this.active_slice != bottom)
- this.set_highlighted_slice((this.active_slice+1)%this.slice_count());
-
- this.key_board_control = true;
+ move_active_slice(this.down_slice_idx, this.up_slice_idx);
}
/////////////////////////////////////////////////////////////////////
@@ -195,17 +476,7 @@ public class PieRenderer : GLib.Object {
/////////////////////////////////////////////////////////////////////
public void select_left() {
- int left = this.slice_count()/2;
- int right = 0;
-
- if (this.active_slice == -1 || this.active_slice == right)
- this.set_highlighted_slice(left);
- else if (this.active_slice > left)
- this.set_highlighted_slice(this.active_slice-1);
- else if (this.active_slice < left)
- this.set_highlighted_slice(this.active_slice+1);
-
- this.key_board_control = true;
+ move_active_slice(this.left_slice_idx, this.right_slice_idx);
}
/////////////////////////////////////////////////////////////////////
@@ -214,17 +485,79 @@ public class PieRenderer : GLib.Object {
/////////////////////////////////////////////////////////////////////
public void select_right() {
- int left = this.slice_count()/2;
- int right = 0;
+ move_active_slice(this.right_slice_idx, this.left_slice_idx);
+ }
- if (this.active_slice == -1 || this.active_slice == left)
- this.set_highlighted_slice(right);
- else if (this.active_slice > left)
- this.set_highlighted_slice((this.active_slice+1)%this.slice_count());
- else if (this.active_slice < left && this.active_slice != right)
- this.set_highlighted_slice((this.active_slice-1+this.slice_count())%this.slice_count());
+ /////////////////////////////////////////////////////////////////////
+ /// Called when the page_up-key is pressed. Selects the next
+ /// group of slices.
+ /////////////////////////////////////////////////////////////////////
- this.key_board_control = true;
+ public void select_nextpage() {
+ if (this.first_slice_idx+this.visible_slice_count < slices.size) {
+ //advance one page
+ this.first_slice_idx += this.visible_slice_count;
+ if (this.first_slice_idx+this.visible_slice_count >= slices.size) {
+ this.visible_slice_count= slices.size - this.first_slice_idx;
+ }
+ this.reset_sclice_anim();
+ this.set_highlighted_slice(-1);
+ calc_key_navigation_pos();
+ this.key_board_control = true;
+
+ } else if (this.first_slice_idx > 0) {
+ //go to first page
+ this.first_slice_idx= 0;
+ this.reset_sclice_anim();
+ //recover the original value
+ this.visible_slice_count= this.original_visible_slice_count;
+ this.reset_sclice_anim();
+ this.set_highlighted_slice(-1);
+ calc_key_navigation_pos();
+ this.key_board_control = true;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Called when the page_down-key is pressed. Selects the previous
+ /// group of slices.
+ /////////////////////////////////////////////////////////////////////
+
+ public void select_prevpage() {
+ if (this.first_slice_idx > 0) {
+ //go back one page
+ //recover the original value
+ this.visible_slice_count= this.original_visible_slice_count;
+ this.first_slice_idx -= this.visible_slice_count;
+ if (this.first_slice_idx < 0) {
+ this.first_slice_idx= 0;
+ }
+ this.reset_sclice_anim();
+ this.set_highlighted_slice(-1);
+ calc_key_navigation_pos();
+ this.key_board_control = true;
+
+ } else if (this.visible_slice_count < slices.size) {
+ //go to last page
+ int n= slices.size % this.original_visible_slice_count;
+ if (n == 0)
+ //all pages have the same number of slices
+ this.visible_slice_count= this.original_visible_slice_count;
+ else
+ //last page has less slices than previous
+ this.visible_slice_count= n;
+ this.first_slice_idx= slices.size - this.visible_slice_count;
+ this.reset_sclice_anim();
+ this.set_highlighted_slice(-1);
+ calc_key_navigation_pos();
+ this.key_board_control = true;
+ }
+ }
+
+ private void reset_sclice_anim() {
+ //reset animation values in all the new visible slices
+ for (int i= 0; i < this.visible_slice_count; ++i)
+ this.slices[ i+this.first_slice_idx ].reset_anim();
}
/////////////////////////////////////////////////////////////////////
@@ -240,41 +573,58 @@ public class PieRenderer : GLib.Object {
/////////////////////////////////////////////////////////////////////
public void draw(double frame_time, Cairo.Context ctx, int mouse_x, int mouse_y) {
- if (this.size > 0) {
- double distance = sqrt(mouse_x*mouse_x + mouse_y*mouse_y);
- double angle = 0.0;
-
- if (this.key_board_control) {
- angle = 2.0*PI*this.active_slice/(double)slice_count();
- } else {
-
- if (distance > 0) {
- angle = acos(mouse_x/distance);
- if (mouse_y < 0)
- angle = 2*PI - angle;
- }
-
- int next_active_slice = this.active_slice;
-
- if (distance < Config.global.theme.active_radius
- && this.quickaction >= 0 && this.quickaction < this.slices.size) {
+ if (this.size_w > 0) {
+ double distance = sqrt(mouse_x*mouse_x + mouse_y*mouse_y);
+ double angle = 0.0;
+ int slice_track= 0;
+
+ if (this.key_board_control) {
+ int n= this.active_slice - this.first_slice_idx;
+ angle = 2.0*PI*n/(double)this.total_slice_count + this.first_slice_angle;
+ slice_track= 1;
+ } else {
+
+ if (distance > 0) {
+ angle = acos(mouse_x/distance);
+ if (mouse_y < 0)
+ angle = 2*PI - angle;
+ }
- next_active_slice = this.quickaction;
- angle = 2.0*PI*quickaction/(double)slice_count();
- } else if (distance > Config.global.theme.active_radius && this.slice_count() > 0 && distance < Config.global.activation_range) {
- next_active_slice = (int)(angle*slices.size/(2*PI) + 0.5) % this.slice_count();
- } else {
- next_active_slice = -1;
- }
+ int next_active_slice = this.active_slice;
+
+ if (distance < Config.global.theme.active_radius
+ && this.quickaction >= this.first_slice_idx
+ && this.quickaction < this.first_slice_idx+this.visible_slice_count) {
+
+ next_active_slice = this.quickaction;
+ int n= this.quickaction - this.first_slice_idx;
+ angle = 2.0*PI*n/(double)this.total_slice_count + this.first_slice_angle;
+
+ } else if (distance > Config.global.theme.active_radius && this.total_slice_count > 0
+ && distance < this.activation_range) {
+ double a= angle-this.first_slice_angle;
+ if (a < 0)
+ a= a + 2*PI;
+ next_active_slice = (int)(a*this.total_slice_count/(2*PI) + 0.5) % this.total_slice_count;
+ if (next_active_slice >= this.visible_slice_count)
+ next_active_slice = -1;
+ else {
+ next_active_slice = next_active_slice + this.first_slice_idx;
+ slice_track= 1;
+ }
+ } else {
+ next_active_slice = -1;
+ }
- this.set_highlighted_slice(next_active_slice);
- }
+ this.set_highlighted_slice(next_active_slice);
+ }
- center.draw(frame_time, ctx, angle, distance);
+ center.draw(frame_time, ctx, angle, slice_track);
- foreach (var slice in this.slices)
- slice.draw(frame_time, ctx, angle, distance);
- }
+ for (int i= 0; i < this.visible_slice_count; ++i) {
+ this.slices[ i+this.first_slice_idx ].draw(frame_time, ctx, angle, slice_track);
+ }
+ }
}
/////////////////////////////////////////////////////////////////////
@@ -291,21 +641,215 @@ public class PieRenderer : GLib.Object {
public void set_highlighted_slice(int index) {
if (index != this.active_slice) {
- if (index >= 0 && index < this.slice_count())
+ if (index >= this.first_slice_idx && index < this.first_slice_idx+this.visible_slice_count)
this.active_slice = index;
- else if (this.quickaction >= 0)
- this.active_slice = this.quickaction;
else
this.active_slice = -1;
- SliceRenderer? active = (this.active_slice >= 0 && this.active_slice < this.slice_count()) ?
+ SliceRenderer? active = (this.active_slice >= 0 && this.active_slice < slices.size) ?
this.slices[this.active_slice] : null;
center.set_active_slice(active);
- foreach (var slice in this.slices)
- slice.set_active_slice(active);
+ for (int i= 0; i < this.visible_slice_count; ++i) {
+ this.slices[ i+this.first_slice_idx ].set_active_slice(active);
+ }
+ }
+ }
+
+ private void set_show_mode(ShowPieMode show_mode) {
+ //The index of the first visible slice
+ this.first_slice_idx= 0;
+ //Angular position of the first visible slice
+ this.first_slice_angle= 0;
+
+ int mult= 1;
+ switch(show_mode) {
+ //half pie
+ case ShowPieMode.HPIE_LEFT:
+ mult= 2;
+ this.first_slice_angle= -PI/2;
+ break;
+ case ShowPieMode.HPIE_RIGHT:
+ mult= 2;
+ this.first_slice_angle= PI/2;
+ break;
+ case ShowPieMode.HPIE_TOP:
+ mult= 2;
+ break;
+ case ShowPieMode.HPIE_BOTTOM:
+ this.first_slice_angle= PI;
+ mult= 2;
+ break;
+
+ //cuarter pie
+ case ShowPieMode.CPIE_TOP_LEFT:
+ mult= 4;
+ break;
+ case ShowPieMode.CPIE_TOP_RIGHT:
+ this.first_slice_angle= PI/2;
+ mult= 4;
+ break;
+ case ShowPieMode.CPIE_BOT_LEFT:
+ this.first_slice_angle= -PI/2;
+ mult= 4;
+ break;
+ case ShowPieMode.CPIE_BOT_RIGHT:
+ this.first_slice_angle= PI;
+ mult= 4;
+ break;
+
+ default: //ShowPieMode.FULL_PIE or invalid values
+ show_mode= ShowPieMode.FULL_PIE;
+ break;
+ }
+ this.pie_show_mode= show_mode;
+ //limit the number of visible slices
+ int maxview= this.max_visible_slices / mult;
+ //Number of visible slices
+ this.visible_slice_count= (int)fmin(slices.size, maxview);
+ //Number of slices in full pie (visible or not)
+ this.total_slice_count= this.visible_slice_count*mult;
+ if (mult > 1 && slices.size > 1) {
+ this.total_slice_count -= mult;
}
+
+ //keep a copy of the original value since page up/down change it
+ original_visible_slice_count= visible_slice_count;
+
+ calc_key_navigation_pos();
+ }
+
+ private void calc_key_navigation_pos() {
+ //calc slices index for keyboard navigation
+
+ int a= this.first_slice_idx;
+ int b= this.first_slice_idx + this.visible_slice_count/4;
+ int c= this.first_slice_idx + this.visible_slice_count/2;
+ int d= this.first_slice_idx + (this.visible_slice_count*3)/4;
+ int e= this.first_slice_idx + this.visible_slice_count -1;
+ switch(this.pie_show_mode) {
+ //half pie
+ case ShowPieMode.HPIE_LEFT:
+ this.up_slice_idx= a;
+ this.right_slice_idx= c;
+ this.down_slice_idx= e;
+ this.left_slice_idx= -1; //no left slice, go up instead
+ break;
+ case ShowPieMode.HPIE_RIGHT:
+ this.down_slice_idx= a;
+ this.left_slice_idx= c;
+ this.up_slice_idx= e;
+ this.right_slice_idx= -1; //no right slice, go down instead
+ break;
+ case ShowPieMode.HPIE_TOP:
+ this.right_slice_idx= a;
+ this.down_slice_idx= c;
+ this.left_slice_idx= e;
+ this.up_slice_idx= -1; //no up slice, go left instead
+ break;
+ case ShowPieMode.HPIE_BOTTOM:
+ this.left_slice_idx= a;
+ this.up_slice_idx= c;
+ this.right_slice_idx= e;
+ this.down_slice_idx= -1; //no down slice, go right instead
+ break;
+
+ //cuarter pie
+ case ShowPieMode.CPIE_TOP_LEFT:
+ this.right_slice_idx= a;
+ this.down_slice_idx= e;
+ this.up_slice_idx= -1; //no up slice, go right instead
+ this.left_slice_idx= -1; //no left slice, go down instead
+ break;
+ case ShowPieMode.CPIE_TOP_RIGHT:
+ this.down_slice_idx= a;
+ this.left_slice_idx= e;
+ this.up_slice_idx= -1; //no up slice, go left instead
+ this.right_slice_idx= -1; //no righ slice, go down instead
+ break;
+ case ShowPieMode.CPIE_BOT_LEFT:
+ this.up_slice_idx= a;
+ this.right_slice_idx= e;
+ this.down_slice_idx= -1; //no down slice, go right instead
+ this.left_slice_idx= -1; //no left slice, go up instead
+ break;
+ case ShowPieMode.CPIE_BOT_RIGHT:
+ this.left_slice_idx= a;
+ this.up_slice_idx= e;
+ this.down_slice_idx= -1; //no down slice, go left instead
+ this.right_slice_idx= -1; //no right slice, go up instead
+ break;
+
+ default: //ShowPieMode.FULL_PIE or invalid values
+ this.right_slice_idx= a;
+ this.down_slice_idx= b;
+ this.left_slice_idx= c;
+ this.up_slice_idx= d;
+ break;
+ }
+ }
+
+
+ /////////////////////////////////////////////////////////////////////
+ /// keyboard navigation helper
+ /// move current position one slice towards the given extreme
+ /////////////////////////////////////////////////////////////////////
+
+ private void move_active_slice(int extreme, int other_extreme ) {
+ int pos= this.active_slice;
+
+ if (pos < 0 || pos == extreme) {
+ //no actual position or allready at the extreme
+ pos= extreme; //go to the extreme pos
+
+ } else if (extreme == -1) {
+ //the extreme was eaten, just go away from the other_extreme
+ if (pos > other_extreme || other_extreme == 0) {
+ if (pos < this.visible_slice_count+this.first_slice_idx-1)
+ pos++;
+ } else if (pos > this.first_slice_idx)
+ pos--;
+
+ } else if (other_extreme == -1) {
+ //the other_extreme was eaten, just get closer to the extreme
+ if (pos < extreme)
+ pos++;
+ else if (pos > extreme)
+ pos--;
+
+ } else if (pos == other_extreme) {
+ //both extremes are present
+ //jump quickly form one extreme to the other
+ pos= extreme; //go to the extreme pos
+
+ } else {
+ //both extremes are present
+ //add or substract 1 to position in a circular manner
+ if (extreme > other_extreme) {
+ if (pos > other_extreme && pos < extreme)
+ //other_extreme < pos < extreme
+ pos= pos+1;
+ else
+ pos= pos-1;
+ } else {
+ if (pos > extreme && pos < other_extreme)
+ //extreme < pos < other_extreme
+ pos= pos-1;
+ else
+ pos= pos+1;
+ }
+
+ if (pos < this.first_slice_idx)
+ pos= this.visible_slice_count-1+this.first_slice_idx;
+
+ if (pos >= this.visible_slice_count+this.first_slice_idx)
+ pos= this.first_slice_idx;
+ }
+
+ this.set_highlighted_slice(pos);
+
+ this.key_board_control = true;
}
}