diff options
| author | Neil Jagdish Patel <neil.patel@canonical.com> | 2010-01-24 15:11:09 +0000 |
|---|---|---|
| committer | Neil Jagdish Patel <neil.patel@canonical.com> | 2010-01-24 15:11:09 +0000 |
| commit | 723e7796c4b01c9c2ff63fffd87d2a75bea61877 (patch) | |
| tree | fb6d87a95aff1bd9f12b3652460aed86b8c9e01b /src | |
| parent | eeb8380627ab2d50065fbbb7eef72b2cfd2d36bb (diff) | |
| parent | a6897bc969cda26ed94f2f7222ec000895ba5784 (diff) | |
[merge, mutter] Merge from upstream, fix input region for panel.
removed: data/gadgets.png data/music.png data/people.png data/photos.png data/quicklauncher_focused_indicator.svg data/quicklauncher_running_indicator.svg data/quicklauncher_spinner.png data/videos.png data/web.png added: data/dash_background.png data/favourites.png data/maximize_up.png data/minimize_up.png data/quicklauncher_focused_indicator.png data/quicklauncher_running_indicator.png src/places/application-place.vala src/places/cairo-drawing.vala src/places/file-place.vala src/places/places-controller.vala src/places/places-model.vala src/places/places-place.vala src/quicklauncher/quicklist-controller.vala src/quicklauncher/quicklist-view.vala renamed: src/places/view.vala => src/places/places-view.vala modified: .bzrignore HACKING configure.ac data/Makefile.am libunity/perf-logger.vala mutter-plugin/Makefile.am mutter-plugin/main.c mutter-plugin/plugin.vala src/Makefile.am src/background.vala src/main.vala src/panel/panel-tray.vala src/panel/panel-view.vala src/places/bar-view.vala src/quicklauncher/application-model.vala src/quicklauncher/launcher-model.vala src/quicklauncher/launcher-view.vala src/quicklauncher/quicklauncher-manager.vala src/quicklauncher/unity-scroller.vala src/window.vala tests/test-unity.vala tools/makebootchart.py vapi/clutk-0.3.vapi vapi/unity-const.vapi src/places/places-view.vala pending merges: Gord Allott 2010-01-22 [merge] Adds a menu item to the quicklists to pin/... Gord Allott 2010-01-22 updated the window code to assign the correct wi... Gord Allott 2010-01-22 added margin to glow effect to get a correct glow Gord Allott 2010-01-22 adds launcher pinning/unpinning to the launcher Neil Jagdish Patel 2010-01-21 [release] 0.1.8 Gord Allott 2010-01-21 [merge] Adds clutter_texture_load_async to the C... Gord Allott 2010-01-21 added async texture loading to clutter textures Gord Allott 2010-01-21 added loading async background texture Neil Jagdish Patel 2010-01-21 [merge] [merge] Jay's places widgets Neil Jagdish Patel 2010-01-21 [data] Removed unecessaray data files Jay Taoko 2010-01-20 Cleanup cairo rendering code. Reuse the code in ca... Neil Jagdish Patel 2010-01-20 [files-place] Update to work better with ... Neil Jagdish Patel 2010-01-20 [application-place] update to work better... Neil Jagdish Patel 2010-01-20 - Make the new views work with upstream U... Neil Jagdish Patel 2010-01-20 [merge] Merge trunk Jay Taoko 2010-01-19 [merge] Added File and Application place content Jay Taoko 2010-01-19 commit Jay Taoko 2010-01-19 commit Jay Taoko 2010-01-19 Prototype File place rendering. Gord Allott 2010-01-20 [merge] updated unity to support new clutk api Gord Allott 2010-01-20 updated quicklist-controller to support new clut... Gord Allott 2010-01-20 [merge] Quicklist controller improvements Gord Allott 2010-01-20 [merge] merge from latest unity Gord Allott 2010-01-19 made append in quicklist-controller actually app... Gord Allott 2010-01-19 added missing vapi, small bugfix for a crasher o... Gord Allott 2010-01-19 [merge] updated to latest unity Gord Allott 2010-01-19 moved as much of the quicklauncher logic from la... Neil Jagdish Patel 2010-01-20 [merge] [merge] Places rework Neil Jagdish Patel 2010-01-20 [mutter] Make mutter work with new stuff Neil Jagdish Patel 2010-01-20 [places-bar] Activate the first place tha... Neil Jagdish Patel 2010-01-20 [places] Add abilty for different places ... Neil Jagdish Patel 2010-01-20 [places-controller/bar/model] Make the co... Neil Jagdish Patel 2010-01-20 [places-view] Remove unnecessary namespacing Neil Jagdish Patel 2010-01-20 [ignores] Update Neil Jagdish Patel 2010-01-20 [places] Cleaned up remaining bits and pi... Neil Jagdish Patel 2010-01-20 [merge] * Merge from upsteam Neil Jagdish Patel 2010-01-19 [places-bar] Make it use the model Neil Jagdish Patel 2010-01-19 Pass model to bar Neil Jagdish Patel 2010-01-19 [places] Some bits-and-pieces to make it ... Gord Allott 2010-01-20 [merge] adds in debugging prints to the drag and... Gord Allott 2010-01-20 added debuging prints to the drag and drop system Jay Taoko 2010-01-19 [merge] Places background pattern. Added image file. Jay Taoko 2010-01-15 Places background pattern. Added image file. Jay Taoko 2010-01-15 [merge] Improved Places bar code. Added code for t... Jay Taoko 2010-01-15 Improved Places bar code. Added code for the trash... Gord Allott 2010-01-15 [merge] menu fix, removed drop shadow that is br... Gord Allott 2010-01-15 removed drop shadow, moved menu removal to ql-co... Neil Jagdish Patel 2010-01-15 [mutter] make disabling mutter work Gord Allott 2010-01-15 [merge] adds fixes to unity to enable the boot l... Gord Allott 2010-01-15 reverted silly change on ctk_init Gord Allott 2010-01-15 updated unity bootlogging to support the mutter-... Gord Allott 2010-01-15 [merge] Seperates out the quicklists from the la... Gord Allott 2010-01-14 added missing ql-controller and -view files Gord Allott 2010-01-14 per commit changes lost so dumping commit log of... Neil Jagdish Patel 2010-01-14 [merge] [merge] Gord's fubuntu fixes Gord Allott 2010-01-12 added support for drag sensitivity, set to 3 pix... Gord Allott 2010-01-12 small fix for scroller animation Gord Allott 2010-01-12 fixed positioning of focused indicator Gord Allott 2010-01-12 removed quicklauncher_spinner.png Gord Allott 2010-01-12 removed glow/dropshadow/throbber, added glow on ... Gord Allott 2010-01-11 removed dropshadow from icons Gord Allott 2010-01-11 added new focuesed indicators (bzr r55.2.6)
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 10 | ||||
| -rw-r--r-- | src/background.vala | 3 | ||||
| -rw-r--r-- | src/main.vala | 33 | ||||
| -rw-r--r-- | src/panel/panel-tray.vala | 10 | ||||
| -rw-r--r-- | src/panel/panel-view.vala | 1 | ||||
| -rw-r--r-- | src/places/application-place.vala | 236 | ||||
| -rw-r--r-- | src/places/bar-view.vala | 272 | ||||
| -rw-r--r-- | src/places/cairo-drawing.vala (renamed from src/places/view.vala) | 239 | ||||
| -rw-r--r-- | src/places/file-place.vala | 239 | ||||
| -rw-r--r-- | src/places/places-controller.vala | 112 | ||||
| -rw-r--r-- | src/places/places-model.vala | 64 | ||||
| -rw-r--r-- | src/places/places-place.vala | 63 | ||||
| -rw-r--r-- | src/places/places-view.vala | 92 | ||||
| -rw-r--r-- | src/quicklauncher/application-model.vala | 179 | ||||
| -rw-r--r-- | src/quicklauncher/launcher-model.vala | 13 | ||||
| -rw-r--r-- | src/quicklauncher/launcher-view.vala | 300 | ||||
| -rw-r--r-- | src/quicklauncher/quicklauncher-manager.vala | 9 | ||||
| -rw-r--r-- | src/quicklauncher/quicklist-controller.vala | 158 | ||||
| -rw-r--r-- | src/quicklauncher/quicklist-view.vala | 48 | ||||
| -rw-r--r-- | src/quicklauncher/unity-scroller.vala | 38 | ||||
| -rw-r--r-- | src/window.vala | 71 |
21 files changed, 1665 insertions, 525 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index c43191cad..5a95c3745 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -71,11 +71,17 @@ panel_sources = \ panel/panel-view.vala places_sources = \ + places/application-place.vala \ places/bar-model.vala \ places/bar-view.vala \ + places/cairo-drawing.vala \ places/default-model.vala \ places/default-view.vala \ - places/view.vala + places/file-place.vala \ + places/places-controller.vala \ + places/places-model.vala \ + places/places-place.vala \ + places/places-view.vala quicklauncher_sources = \ quicklauncher/application-model.vala \ @@ -84,6 +90,8 @@ quicklauncher_sources = \ quicklauncher/prism-handler.vala \ quicklauncher/quicklauncher-manager.vala \ quicklauncher/quicklauncher.vala \ + quicklauncher/quicklist-controller.vala \ + quicklauncher/quicklist-view.vala \ quicklauncher/tooltipmanager.vala \ quicklauncher/unity-scroller.vala diff --git a/src/background.vala b/src/background.vala index 1d4290de3..dcf686d0f 100644 --- a/src/background.vala +++ b/src/background.vala @@ -33,6 +33,7 @@ namespace Unity construct { + START_FUNCTION (); var client = GConf.Client.get_default (); /* Setup the initial properties and notifies */ @@ -83,11 +84,13 @@ namespace Unity /* The texture that will show the background */ this.bg = new Clutter.Texture (); + this.bg.set_load_async (true); this.add_actor (this.bg); this.bg.show (); /* Load the texture */ this.ensure_layout (); + END_FUNCTION (); } private void on_filename_changed (GConf.Client client, diff --git a/src/main.vala b/src/main.vala index 1fbdfd937..30f86bf13 100644 --- a/src/main.vala +++ b/src/main.vala @@ -23,7 +23,7 @@ static bool popup_mode = false; static int popup_width = 1024; static int popup_height = 600; static bool show_version = false; -static string? boot_logging_filename = null; +static string? boot_logging_filename = null; const OptionEntry[] options = { { @@ -72,15 +72,6 @@ const OptionEntry[] options = { null }, { - "enable-boot-logging", - 'b', - OptionFlags.FILENAME, - OptionArg.FILENAME, - ref boot_logging_filename, - "enables boot logging, requires filename argument", - null - }, - { null } }; @@ -113,14 +104,11 @@ public class Main print ("\nUnity %s\n", "0.1.0"); return 0; } - + // attempt to get a boot logging filename + boot_logging_filename = Environment.get_variable ("UNITY_BOOTLOG_FILENAME"); if (boot_logging_filename != null) { Unity.is_logging = true; - Timeout.add_seconds (3, () => { - Unity.TimelineLogger.get_default().write_log (boot_logging_filename); - return false; - }); } else { @@ -129,11 +117,17 @@ public class Main START_FUNCTION (); /* Parse options */ + LOGGER_START_PROCESS ("gtk_init"); Gtk.init (ref args); + LOGGER_END_PROCESS ("gtk_init"); + LOGGER_START_PROCESS ("ctk_init"); Ctk.init (ref args); + LOGGER_END_PROCESS ("ctk_init"); /* Unique instancing */ + LOGGER_START_PROCESS ("unity_application_constructor"); app = new Unity.Application (); + LOGGER_END_PROCESS ("unity_application_constructor"); if (app.is_running) { Unique.Response response = Unique.Response.OK; @@ -154,10 +148,19 @@ public class Main /* Things seem to be okay, load the main window */ window = new Unity.UnderlayWindow (popup_mode, popup_width, popup_height); app.shell = window; + LOGGER_START_PROCESS ("unity_underlay_window_show"); window.show (); + LOGGER_END_PROCESS ("unity_underlay_window_show"); END_FUNCTION (); + if (boot_logging_filename != null) + { + Timeout.add_seconds (1, () => { + Unity.TimelineLogger.get_default().write_log (boot_logging_filename); + return false; + }); + } Gtk.main (); diff --git a/src/panel/panel-tray.vala b/src/panel/panel-tray.vala index 9f5a0b6b0..61332eb85 100644 --- a/src/panel/panel-tray.vala +++ b/src/panel/panel-tray.vala @@ -18,6 +18,8 @@ * */ +using Gee; + namespace Unity.Panel.Tray { public class View : Ctk.Box @@ -27,12 +29,12 @@ namespace Unity.Panel.Tray public View () { - Object (orientation:Ctk.Orientation.HORIZONTAL); + Object (orientation:Ctk.Orientation.HORIZONTAL, + spacing:6); } construct { - Clutter.Color color = { 0, 0, 0, 255 }; this.manager = new TrayManager (); this.manager.tray_icon_added.connect (this.on_tray_icon_added); this.manager.tray_icon_removed.connect (this.on_tray_icon_removed); @@ -41,7 +43,7 @@ namespace Unity.Panel.Tray public void manage_stage (Clutter.Stage stage) { this.stage = stage; - //this.manager.manage_stage (stage); + Idle.add (this.manage_tray_idle); } @@ -53,7 +55,6 @@ namespace Unity.Panel.Tray private void on_tray_icon_added (Clutter.Actor icon) { - debug ("Icon added"); this.add_actor (icon); icon.opacity = 100; icon.set_size (23, 23); @@ -62,7 +63,6 @@ namespace Unity.Panel.Tray private void on_tray_icon_removed (Clutter.Actor icon) { - debug ("Icon removed"); this.remove_actor (icon); } } diff --git a/src/panel/panel-view.vala b/src/panel/panel-view.vala index ef7f73739..9243bd92e 100644 --- a/src/panel/panel-view.vala +++ b/src/panel/panel-view.vala @@ -34,7 +34,6 @@ namespace Unity.Panel public View (Shell shell) { - debug ("View"); Object (shell:shell); this.tray.manage_stage (this.shell.get_stage ()); } diff --git a/src/places/application-place.vala b/src/places/application-place.vala new file mode 100644 index 000000000..4dd04c4b2 --- /dev/null +++ b/src/places/application-place.vala @@ -0,0 +1,236 @@ + +namespace Unity.Places.Application +{ + + const string APP_ICON = Unity.PKGDATADIR + "/applications.png"; + const string FAVOURITES_ICON = Unity.PKGDATADIR + "/favourites.png"; + const string MINIMIZE_ICON = Unity.PKGDATADIR + "/minimize_up.png"; + const string MAXIMIZE_ICON = Unity.PKGDATADIR + "/maximize_up.png"; + + public class ApplicationIcon + { + private Unity.Places.Bar.Model model; + public Ctk.Image view; + public Ctk.Text label; + + public ApplicationIcon (int width, /*int height,*/ string name, string icon_name, string tooltip) + { + model = new Unity.Places.Bar.Model (name, icon_name, tooltip); + view = new Ctk.Image.from_filename (width, icon_name); + view.set_reactive (true); + label = new Ctk.Text (name); + } + } + + public class ApplicationGroup : Ctk.Box + { + private Ctk.Text GroupName; + private Ctk.Image Star; + private Unity.Places.CairoDrawing.PlacesHSeparator Separator; + private Ctk.Image maximize_button; + private Ctk.Image minimize_button; + private bool is_open; + private Gee.ArrayList<ApplicationIcon> application_icon_array; + + + public override void allocate (Clutter.ActorBox box, + Clutter.AllocationFlags flags) + { + int IconWidth = 48; + int IconHeight = 48; + int ApplicationIconSpacing = 100; + + int HeaderBorderPositionX = 0; + int HeaderBorderPositionY = 60; + int IconBorderPositionX = 0; + int IconBorderPositionY = 100; + int LineBorderPositionX = 0; + int LineBorderPositionY = 90; + + Clutter.ActorBox child_box = { 0.0f, 0.0f, 0.0f, 0.0f }; + + base.allocate (box, flags); + + child_box.x1 = IconBorderPositionX; + child_box.x2 = 0; + child_box.y1 = IconBorderPositionY; + child_box.y2 = child_box.y1 + IconHeight; + + int i; + for (i = 0; i < this.application_icon_array.size; i++) + { + child_box.x2 = child_box.x1 + IconWidth; + this.application_icon_array[i].view.allocate(child_box, flags); + + Clutter.ActorBox label_box = { 0.0f, 0.0f, 0.0f, 0.0f }; + label_box.x1 = child_box.x1; + label_box.x2 = child_box.x2; + label_box.y1 = IconBorderPositionY + IconHeight; + label_box.y2 = label_box.y1 + 64; + this.application_icon_array[i].label.allocate(label_box, flags); + + child_box.x1 += IconWidth + ApplicationIconSpacing; + } + + if (this.Separator.Width != 800) + { + this.Separator.CreateSeparator ( 800, 5); + } + child_box.x1 = LineBorderPositionX; + child_box.x2 = child_box.x1 + 800; + child_box.y1 = LineBorderPositionY; + child_box.y2 = LineBorderPositionY + 5; + this.Separator.allocate (child_box, flags); + + child_box.x1 = HeaderBorderPositionX; + child_box.x2 = child_box.x1 + 22; + child_box.y1 = HeaderBorderPositionY; + child_box.y2 = HeaderBorderPositionY+ 23; + this.Star.allocate (child_box, flags); + + child_box.x1 = HeaderBorderPositionX + 22; + child_box.x2 = child_box.x1 + 100; + child_box.y1 = HeaderBorderPositionY; + child_box.y2 = HeaderBorderPositionY + 23; + this.GroupName.allocate (child_box, flags); + + child_box.x1 += 750; + child_box.x2 = child_box.x1 + 16; + child_box.y1 = HeaderBorderPositionY; + child_box.y2 = HeaderBorderPositionY + 19; + this.maximize_button.allocate (child_box, flags); + this.minimize_button.allocate (child_box, flags); + } + + public override void get_preferred_width (float for_height, + out float minimum_width, + out float natural_width) + { + minimum_width = 800.0f; + natural_width = 800.0f; + } + + public override void get_preferred_height (float for_width, + out float minimum_height, + out float natural_height) + { + minimum_height = 150.0f; + natural_height = 150.0f; + } + + public ApplicationGroup (string group_name) + { + this.homogeneous = false; + this.orientation = Ctk.Orientation.HORIZONTAL; + + this.GroupName = new Ctk.Text (group_name); + this.Star = new Ctk.Image.from_filename (23, FAVOURITES_ICON); + this.Separator = new Unity.Places.CairoDrawing.PlacesHSeparator (); + this.maximize_button = new Ctk.Image.from_filename (16, MAXIMIZE_ICON); + this.minimize_button = new Ctk.Image.from_filename (16, MINIMIZE_ICON); + + application_icon_array = new Gee.ArrayList<ApplicationIcon> (); + for (int i = 0; i < 5; i++) + { + ApplicationIcon app = new ApplicationIcon (48, "App", + APP_ICON, + "Your apps stored locally"); + this.application_icon_array.add (app); + this.add_actor (app.view); + this.add_actor (app.label); + } + + this.add_actor (this.Star); + this.add_actor (this.Separator); + this.add_actor (this.GroupName); + this.add_actor (this.maximize_button); + this.add_actor (this.minimize_button); + + this.is_open = true; + this.show_all (); + + this.maximize_button.set_reactive (true); + this.minimize_button.set_reactive (true); + this.maximize_button.hide(); + this.minimize_button.show(); + + this.maximize_button.button_release_event.connect (this.on_maximize); + this.minimize_button.button_release_event.connect (this.on_minimize); + } + + construct + { + } + + public bool on_minimize (Clutter.Event event) + { + this.maximize_button.show(); + this.minimize_button.hide(); + this.is_open = false; + return false; + } + + public bool on_maximize (Clutter.Event event) + { + this.maximize_button.hide(); + this.minimize_button.show(); + this.is_open = true; + return false; + } + } + + public class ApplicationView : Ctk.Box + { + public ApplicationGroup recent_app_group; + public ApplicationGroup yesterday_app_group; + public ApplicationGroup lastweek_app_group; + public override void allocate (Clutter.ActorBox box, + Clutter.AllocationFlags flags) + { + Clutter.ActorBox child_box = { 0.0f, 0.0f, 0.0f, 0.0f }; + float width, height; + float child_width, child_height; + + base.allocate (box, flags); + + width = box.x2 - box.x1; + height = box.y2 - box.y1; + + this.recent_app_group.get_preferred_width (height, + out child_width, + out child_width); + this.recent_app_group.get_preferred_height (width, + out child_height, + out child_height); + child_box.x1 = (width - child_width)/2.0f; + child_box.x2 = child_box.x1 + child_width; + child_box.y1 = 0.0f; + child_box.y2 = child_height; + recent_app_group.allocate (child_box, flags); + + child_box.y1 += child_height; + child_box.y2 = child_box.y1 + child_height; + yesterday_app_group.allocate (child_box, flags); + + child_box.y1 += child_height; + child_box.y2 = child_box.y1 + child_height; + lastweek_app_group.allocate (child_box, flags); + } + + public ApplicationView () + { + recent_app_group = new ApplicationGroup ("Recent apps"); + yesterday_app_group = new ApplicationGroup ("Yesterday apps"); + lastweek_app_group = new ApplicationGroup ("Last week apps"); + + this.add_actor (recent_app_group); + this.add_actor (yesterday_app_group); + this.add_actor (lastweek_app_group); + this.show_all (); + } + + construct + { + } + } +} diff --git a/src/places/bar-view.vala b/src/places/bar-view.vala index c81610436..f443c308a 100644 --- a/src/places/bar-view.vala +++ b/src/places/bar-view.vala @@ -14,137 +14,223 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Authored by Mirco "MacSlow" Müller <mirco.mueller@canonical.com> + * Neil Jagdish Patel <neil.patel@canonical.com> * */ namespace Unity.Places.Bar { - const string APPS_FILE = Unity.PKGDATADIR + "/applications.png"; - const string FILES_FILE = Unity.PKGDATADIR + "/files.png"; - const string GADGETS_FILE = Unity.PKGDATADIR + "/gadgets.png"; - const string HOME_FILE = Unity.PKGDATADIR + "/home.png"; - const string MUSIC_FILE = Unity.PKGDATADIR + "/music.png"; - const string PEOPLE_FILE = Unity.PKGDATADIR + "/people.png"; - const string PHOTOS_FILE = Unity.PKGDATADIR + "/photos.png"; - const string SOFTWARECENTER_FILE = Unity.PKGDATADIR + "/software_centre.png"; + const float PANEL_HEIGHT = 24; + const int ICON_SIZE = 48; + const float ICON_VIEW_WIDTH = 80.0f; + const float ICON_VIEW_Y1 = 8.0f; + const float QL_PAD = 12.0f; + const string TRASH_FILE = Unity.PKGDATADIR + "/trash.png"; - const string VIDEOS_FILE = Unity.PKGDATADIR + "/videos.png"; - const string WEB_FILE = Unity.PKGDATADIR + "/web.png"; public class View : Ctk.Box { - private Gee.ArrayList<Unity.Places.Bar.Model> places; - private Gee.ArrayList<Ctk.Image> icon_view; + public Places.Model model { get; construct; } + + private Gee.ArrayList<PlaceIcon> places_icons; + private PlaceIcon trash_icon; - public signal void sig_active_icon_index (int i); + private Unity.Places.CairoDrawing.PlacesVSeparator separator; + private Unity.Places.CairoDrawing.PlacesBackground bg; - public View () + public View (Places.Model model) { - Unity.Places.Bar.Model place; - int i; - Ctk.Image icon; - int icon_size = 48; Ctk.EffectGlow glow; Clutter.Color white = {255, 255, 255, 255}; + Object (model:model); + + /* We do our own allocation, but this doesn't hurt */ this.homogeneous = false; - this.spacing = icon_size/2; - this.orientation = Ctk.Orientation.HORIZONTAL; // this sucks - - this.places = new Gee.ArrayList<Unity.Places.Bar.Model> (); - this.icon_view = new Gee.ArrayList<Ctk.Image> (); - - // populate places-bar with hard-coded contents for the moment - place = new Unity.Places.Bar.Model ("Home", - HOME_FILE, - "Default View"); - this.places.add (place); - - place = new Unity.Places.Bar.Model ("Applications", - APPS_FILE, - "Programs installed locally"); - this.places.add (place); - - place = new Unity.Places.Bar.Model ("Files", - FILES_FILE, - "Your files stored locally"); - this.places.add (place); - - place = new Unity.Places.Bar.Model ("Music", - MUSIC_FILE, - "Soothing sounds and vibes"); - this.places.add (place); - - place = new Unity.Places.Bar.Model ("People", - PEOPLE_FILE, - "Friends, pals, mates and folks"); - this.places.add (place); - - place = new Unity.Places.Bar.Model ("Photos", - PHOTOS_FILE, - "Pretty pictures presented by pixels"); - this.places.add (place); - - place = new Unity.Places.Bar.Model ("Trash", - TRASH_FILE, - "Your piece of waste"); - this.places.add (place); - - /* create all image-actors for icons */ - for (i = 0; i < this.places.size ; i++) - { - icon = new Ctk.Image.from_filename (icon_size, this.places[i].icon_name); - icon.set_reactive (true); - - glow = new Ctk.EffectGlow (); - glow.set_color (white); - glow.set_factor (1.0f); - icon.add_effect (glow); - - this.icon_view.add (icon); - this.pack (icon, false, false); - icon.enter_event.connect (this.on_enter); - icon.leave_event.connect (this.on_leave); - icon.button_press_event.connect (this.on_button_press); - } + this.orientation = Ctk.Orientation.HORIZONTAL; + + /* The background of the entire places bar */ + this.bg = new Unity.Places.CairoDrawing.PlacesBackground (); + this.bg.set_parent (this); + this.bg.show (); + + /* This'll be populated in an idle by the model */ + this.places_icons = new Gee.ArrayList<PlaceIcon> (); + this.model.place_added.connect (this.on_place_added); + + /* Create trash icon */ + this.trash_icon = new PlaceIcon (ICON_SIZE, + "Trash", + TRASH_FILE, + "Your piece of waste"); + glow = new Ctk.EffectGlow (); + glow.set_color (white); + glow.set_factor (1.0f); + glow.set_margin (6); + this.trash_icon.add_effect (glow); + + this.pack (this.trash_icon, false, false); + this.trash_icon.button_release_event.connect (this.on_button_release); + + /* Create the separator */ + this.separator = new Unity.Places.CairoDrawing.PlacesVSeparator (); + this.pack (this.separator, false, false); this.show_all (); } - public int get_number_of_items () + private void on_place_added (Place place) { - return this.places.size; + Clutter.Color white = {255, 255, 255, 255}; + + var icon = new PlaceIcon.from_place (ICON_SIZE, place); + this.places_icons.add (icon); + + var glow = new Ctk.EffectGlow (); + glow.set_color (white); + glow.set_factor (1.0f); + glow.set_margin (6); + icon.add_effect (glow); + + this.pack (icon, false, false); + icon.button_release_event.connect (this.on_button_release); + + if (this.places_icons.size == 1) + { + Clutter.Actor stage = icon.get_stage (); + this.bg.create_places_background ((int)stage.width, + (int)stage.height, + (int)(this.padding.left + QL_PAD), + (int)ICON_VIEW_WIDTH); + + icon.place.active = true; + } } - public bool on_enter () + public override void map () { - /* stdout.printf ("on_enter() called\n"); */ - return false; + base.map (); + this.bg.map (); } - public bool on_leave () + public override void unmap () { - /* stdout.printf ("on_leave() called\n"); */ - return false; + base.unmap (); + this.bg.unmap (); + } + + public override void paint () + { + this.bg.paint (); + base.paint (); + } + + public override void allocate (Clutter.ActorBox box, + Clutter.AllocationFlags flags) + { + Clutter.ActorBox child_box = {0, 0, 0, 0}; + child_box.x1 = 0.0f; + child_box.x2 = box.x2 - box.x1; + child_box.y1 = 0.0f; + child_box.y2 = box.y2 - box.y1; + + this.bg.allocate (child_box, flags); + + /* Allocate the places icons */ + var n_places = 0; + var lpadding = this.padding.left + QL_PAD; + + child_box.y1 = ICON_VIEW_Y1; + child_box.y2 = child_box.y1 + ICON_SIZE; + + foreach (PlaceIcon place in this.places_icons) + { + child_box.x1 = lpadding + (ICON_VIEW_WIDTH * n_places); + child_box.x2 = child_box.x1 + ICON_VIEW_WIDTH; + + place.allocate (child_box, flags); + + n_places++; + } + + /* Allocate the Trash */ + child_box.x1 = box.x2 - box.x1 - 266 - ICON_VIEW_WIDTH; + child_box.x2 = child_box.x1 + ICON_VIEW_WIDTH; + this.trash_icon.allocate (child_box, flags); + + /* Allocate the seperator */ + child_box.x1 -= 12.0f; + child_box.x2 = child_box.x1 + 5; + child_box.y1 = 10; + child_box.y2 = ICON_SIZE; + this.separator.allocate (child_box, flags); } - public bool on_button_press (Clutter.Event event) + public bool on_button_release (Clutter.Event event) { - int i; Clutter.Actor actor; actor = event.button.source; - for (i = 0; i < this.icon_view.size ; i++) - { - if (actor == this.icon_view[i]) - sig_active_icon_index(i); - } + if (actor is PlaceIcon) + { + PlaceIcon icon = actor as PlaceIcon; + + /* Do something with the click */ + if (actor == this.trash_icon) + { + try + { + Process.spawn_command_line_async ("xdg-open trash:///"); + } + catch (SpawnError e) + { + warning ("Unable to show Trash: %s", e.message); + } + } + else if (icon.place is Place) + { + Clutter.Actor stage = actor.get_stage (); + + /* Update the background */ + this.bg.create_places_background ((int)stage.width, + (int)stage.height, + (int)actor.x, + 80); + + /* Set the place as active, unset the others */ + foreach (PlaceIcon picon in this.places_icons) + { + if (picon.place is Place) + picon.place.active = (picon == icon) ? true : false; + } + } + + return true; + } return false; } + } + + public class PlaceIcon : Ctk.Image + { + public Place? place { get; set; } + + public PlaceIcon (int width, + string name, + string icon_name, + string tooltip) + { + Object (size:width); + + this.set_from_filename (icon_name); + this.reactive = true; + } - construct + public PlaceIcon.from_place (int size, Place place) { + this(size, place.name, place.icon_name, ""); + this.place = place; } } } diff --git a/src/places/view.vala b/src/places/cairo-drawing.vala index 782adf8b2..8c460274c 100644 --- a/src/places/view.vala +++ b/src/places/cairo-drawing.vala @@ -13,12 +13,17 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * - * Authored by Mirco "MacSlow" Müller <mirco.mueller@canonical.com> + * Authored by Jay Taoko <jay.taoko@canonical.com> * */ -namespace Unity.Places +namespace Unity.Places.CairoDrawing { + /* Margin outside of the cairo texture. We draw outside to complete the line loop + * and we don't want the line loop to be visible in some parts of the screen. + * */ + private int Margin = 5; + public class PlacesBackground : Ctk.Bin { public Clutter.CairoTexture cairotxt; @@ -35,11 +40,6 @@ namespace Unity.Places private int PlaceBottom; /* PlaceY + PlaceH */ - /* Margin outside of the cairo texture. We draw outside to complete the line loop - * and we don't want the line loop to be visible in some parts of the screen. - * */ - private int Margin = 20; - /* Menu area width and height */ private int MenuH = 22; private int MenuW = 216; @@ -123,7 +123,7 @@ namespace Unity.Places PlaceWidth = 0; } - public void CreatePlacesBackground (int WindowWidth, + public void create_places_background (int WindowWidth, int WindowHeight, int TabPositionX, int TabWidth) @@ -133,12 +133,19 @@ namespace Unity.Places PlaceBottom = PlaceY + PlaceH; MenuBottom = PlaceY + MenuH; - if (cairotxt != null) - this.remove_actor (cairotxt); + if (this.get_child () is Clutter.Actor) + { + this.remove_actor (this.get_child ()); + } - cairotxt = new Clutter.CairoTexture(PlaceW, PlaceH); + cairotxt = new Clutter.CairoTexture(PlaceW, PlaceH + Margin); Cairo.Context cairoctx = cairotxt.create(); { + /* Clear */ + /*cairoctx.set_operator (Cairo.Operator.CLEAR); + cairoctx.paint (); + cairoctx.set_operator (Cairo.Operator.OVER);*/ + cairoctx.set_source_rgba (1, 1, 1, 1.0); cairoctx.set_line_width (1.0); @@ -161,13 +168,25 @@ namespace Unity.Places cairoctx.line_to (PlaceX - Margin, PlaceY - Margin); cairoctx.stroke_preserve (); - cairoctx.set_source_rgba (1, 1, 1, 0.15); - cairoctx.fill (); + + cairoctx.clip (); + + Cairo.Surface surface = new Cairo.ImageSurface.from_png (Unity.PKGDATADIR + "/dash_background.png"); + Cairo.Pattern pattern = new Cairo.Pattern.for_surface (surface); + pattern.set_extend (Cairo.Extend.REPEAT); + cairoctx.set_source (pattern); + + cairoctx.paint_with_alpha (0.1); } cairotxt.set_opacity (0xFF); this.add_actor (cairotxt); + /* Remove all effects set on this actor */ + this.remove_all_effects (); + + /* Create a new effect and add it to this actor */ + /* The new effect will use the newly created drawing as a base */ effect_glow = new Ctk.EffectGlow (); Clutter.Color c = Clutter.Color () { @@ -179,6 +198,7 @@ namespace Unity.Places effect_glow.set_color (c); effect_glow.set_factor (1.0f); + effect_glow.set_margin (5); this.add_effect (effect_glow); } @@ -187,122 +207,127 @@ namespace Unity.Places } } - public class View : Ctk.Box - { - private Unity.Places.Bar.View bar_view; - private Unity.Places.Default.View default_view; - private Gee.ArrayList<PlacesBackground> background_array; - private int current_tab_index; - /* These parameters are temporary until we get the right metrics for the places bar */ + public class PlacesVSeparator : Ctk.Bin + { + public int Width = 0; + public int Height = 0; - public override void allocate (Clutter.ActorBox box, - Clutter.AllocationFlags flags) + public Clutter.CairoTexture cairotxt; + public PlacesVSeparator () { - base.allocate (box, flags); - Clutter.ActorBox child_box = { 0.0f, 0.0f, 0.0f, 0.0f }; - int bar_icon_size = 48; /* HARDCODED: height of icons in places bar */ - int icon_margin = 4; - int offset = 94; /* offset to first icon */ - int NewPlaceWidth = (int) (box.x2 - box.x1); - - child_box.x1 = offset; //this.padding.left; - child_box.x2 = box.x2 - box.x1 - this.padding.left - this.padding.right; - child_box.y1 = this.padding.top + 8; - child_box.y2 = child_box.y1 + bar_icon_size; - this.bar_view.allocate (child_box, flags); - - - child_box.x1 = box.x1 + 58 /* HARDCODED: width of quicklauncher */; - child_box.x2 = box.x2; - child_box.y1 = box.y1 + 55 /* HARDCODED: height of Places bar */; - child_box.y2 = box.y2; - - this.default_view.allocate (child_box, flags); - - child_box.x1 = 0; - child_box.x2 = NewPlaceWidth; - child_box.y1 = 0; - child_box.y2 = 55; - - int spacing = this.bar_view.spacing; - int i; - for (i = 0; i < this.background_array.size; i++) - { - if (this.background_array[i].PlaceWidth != NewPlaceWidth) - { - this.background_array[i].CreatePlacesBackground (NewPlaceWidth, 55, - offset + i*(bar_icon_size + spacing) - icon_margin, - 2*icon_margin + bar_icon_size); - } - this.background_array[i].allocate (child_box, flags); - } } - public View () + public void CreateSeparator (int W, int H) { - int i; - int NunItems; - PlacesBackground placesbackground; + Width = W; + Height = H; - this.background_array = new Gee.ArrayList<PlacesBackground> (); - - this.current_tab_index = 0; - this.orientation = Ctk.Orientation.VERTICAL; - this.bar_view = new Unity.Places.Bar.View (); - this.bar_view.sig_active_icon_index.connect(this.on_signal_active_icon); - - this.default_view = new Unity.Places.Default.View (); + if (this.get_child () is Clutter.Actor) + { + this.remove_actor (this.get_child ()); + } - NunItems = this.bar_view.get_number_of_items (); - for (i = 0; i < NunItems; i++) + cairotxt = new Clutter.CairoTexture(Width, Height); + Cairo.Context cairoctx = cairotxt.create(); { - placesbackground = new PlacesBackground (); - this.add_actor (placesbackground); - this.background_array.add (placesbackground); - placesbackground.hide (); + cairoctx.set_source_rgba (1, 1, 1, 1.0); + cairoctx.set_line_width (1.0); + + cairoctx.move_to (Width/2.0, 0); + cairoctx.line_to (Width/2.0, Height); + + cairoctx.stroke (); + cairoctx.set_source_rgba (1, 1, 1, 0.15); } - this.background_array[0].show (); - this.add_actor (this.bar_view); - this.add_actor (this.default_view); + cairotxt.set_opacity (0xFF); + this.add_actor (cairotxt); + + /* Remove all effects set on this actor */ + this.remove_all_effects (); + + /* Create a new effect and add it to this actor */ + /* The new effect will use the newly created drawing as a base */ + Ctk.EffectGlow effect_glow = new Ctk.EffectGlow (); + Clutter.Color c = Clutter.Color () + { + red = 255, + green = 255, + blue = 255, + alpha = 255 + }; - Ctk.Padding padding = { 0.0f, 0.0f, 0.0f, 12.0f }; - this.set_padding (padding); + effect_glow.set_color (c); + effect_glow.set_factor (1.0f); + effect_glow.set_margin (5); + this.add_effect (effect_glow); } - public void set_size_and_position (int bar_x, - int bar_y, - int bar_w, - int bar_h, - int def_view_x, - int def_view_y, - int def_view_w, - int def_view_h) + construct { - this.bar_view.x = bar_x; - this.bar_view.y = bar_y; - this.bar_view.width = bar_w; - this.bar_view.height = bar_h; - - this.default_view.x = def_view_x; - this.default_view.y = def_view_y; - this.default_view.width = def_view_w; - this.default_view.height = def_view_h; } + } - construct + public class PlacesHSeparator : Ctk.Bin + { + public int Width = 0; + public int Height = 0; + + public Clutter.CairoTexture cairotxt; + public PlacesHSeparator () { } - public void on_signal_active_icon (int i) + public void CreateSeparator (int W, int H) { - if (i >= this.background_array.size) - return; + Width = W; + Height = H; - this.background_array[this.current_tab_index].hide (); - this.current_tab_index = i; - this.background_array[this.current_tab_index].show (); + if (this.get_child () is Clutter.Actor) + { + this.remove_actor (this.get_child ()); + } + + cairotxt = new Clutter.CairoTexture(Width, Height); + Cairo.Context cairoctx = cairotxt.create(); + { + cairoctx.set_source_rgba (1, 1, 1, 1.0); + cairoctx.set_line_width (1.0); + + cairoctx.move_to (0, Height/2.0); + cairoctx.line_to (Width, Height/2.0); + + cairoctx.stroke (); + cairoctx.set_source_rgba (1, 1, 1, 0.15); + } + + cairotxt.set_opacity (0xFF); + this.add_actor (cairotxt); + + /* Remove all effects set on this actor */ + this.remove_all_effects (); + + /* Create a new effect and add it to this actor */ + /* The new effect will use the newly created drawing as a base */ + + Ctk.EffectGlow effect_glow = new Ctk.EffectGlow (); + Clutter.Color c = Clutter.Color () + { + red = 255, + green = 255, + blue = 255, + alpha = 255 + }; + + effect_glow.set_color (c); + effect_glow.set_factor (1.0f); + effect_glow.set_margin (5); + this.add_effect (effect_glow); + } + + construct + { } } } diff --git a/src/places/file-place.vala b/src/places/file-place.vala new file mode 100644 index 000000000..e322cd0c4 --- /dev/null +++ b/src/places/file-place.vala @@ -0,0 +1,239 @@ + +namespace Unity.Places.File +{ + + const string FILES_FILE = Unity.PKGDATADIR + "/files.png"; + const string FAVOURITES_ICON = Unity.PKGDATADIR + "/favourites.png"; + const string MINIMIZE_ICON = Unity.PKGDATADIR + "/minimize_up.png"; + const string MAXIMIZE_ICON = Unity.PKGDATADIR + "/maximize_up.png"; + + public class FileIcon + { + private Unity.Places.Bar.Model model; + public Ctk.Image view; + public Ctk.Text label; + + public FileIcon (int width, /*int height,*/ string name, string icon_name, string tooltip) + { + model = new Unity.Places.Bar.Model (name, icon_name, tooltip); + view = new Ctk.Image.from_filename (width, icon_name); + view.set_reactive (true); + label = new Ctk.Text (name); + } + } + + public class FileGroup : Ctk.Box + { + private Ctk.Text GroupName; + private Ctk.Image Star; + private Unity.Places.CairoDrawing.PlacesHSeparator Separator; + private Ctk.Image maximize_button; + private Ctk.Image minimize_button; + private bool is_open; + private Gee.ArrayList<FileIcon> file_icon_array; + + + public override void allocate (Clutter.ActorBox box, + Clutter.AllocationFlags flags) + { + int IconWidth = 48; + int IconHeight = 48; + int FileIconSpacing = 100; + + int HeaderBorderPositionX = 0; + int HeaderBorderPositionY = 60; + int IconBorderPositionX = 0; + int IconBorderPositionY = 100; + int LineBorderPositionX = 0; + int LineBorderPositionY = 90; + + Clutter.ActorBox child_box = { 0.0f, 0.0f, 0.0f, 0.0f }; + + base.allocate (box, flags); + + child_box.x1 = IconBorderPositionX; + child_box.x2 = 0; + child_box.y1 = IconBorderPositionY; + child_box.y2 = child_box.y1 + IconHeight; + + int i; + for (i = 0; i < this.file_icon_array.size; i++) + { + child_box.x2 = child_box.x1 + IconWidth; + this.file_icon_array[i].view.allocate(child_box, flags); + + Clutter.ActorBox label_box = { 0.0f, 0.0f, 0.0f, 0.0f }; + label_box.x1 = child_box.x1; + label_box.x2 = child_box.x2; + label_box.y1 = IconBorderPositionY + IconHeight; + label_box.y2 = label_box.y1 + 64; + this.file_icon_array[i].label.allocate(label_box, flags); + + child_box.x1 += IconWidth + FileIconSpacing; + } + + if (this.Separator.Width != 800) + { + this.Separator.CreateSeparator ( 800, 5); + } + child_box.x1 = LineBorderPositionX; + child_box.x2 = child_box.x1 + 800; + child_box.y1 = LineBorderPositionY; + child_box.y2 = LineBorderPositionY + 5; + this.Separator.allocate (child_box, flags); + + child_box.x1 = HeaderBorderPositionX; + child_box.x2 = child_box.x1 + 22; + child_box.y1 = HeaderBorderPositionY; + child_box.y2 = HeaderBorderPositionY+ 23; + this.Star.allocate (child_box, flags); + + child_box.x1 = HeaderBorderPositionX + 22; + child_box.x2 = child_box.x1 + 100; + child_box.y1 = HeaderBorderPositionY; + child_box.y2 = HeaderBorderPositionY + 23; + this.GroupName.allocate (child_box, flags); + + child_box.x1 += 750; + child_box.x2 = child_box.x1 + 16; + child_box.y1 = HeaderBorderPositionY; + child_box.y2 = HeaderBorderPositionY + 19; + this.maximize_button.allocate (child_box, flags); + this.minimize_button.allocate (child_box, flags); + } + + public override void get_preferred_width (float for_height, + out float minimum_width, + out float natural_width) + { + minimum_width = 800.0f; + natural_width = 800.0f; + } + + public override void get_preferred_height (float for_width, + out float minimum_height, + out float natural_height) + { + minimum_height = 150.0f; + natural_height = 150.0f; + } + + + public FileGroup (string group_name) + { + this.homogeneous = false; + this.orientation = Ctk.Orientation.HORIZONTAL; + + this.GroupName = new Ctk.Text (group_name); + this.Star = new Ctk.Image.from_filename (23, FAVOURITES_ICON); + this.Separator = new Unity.Places.CairoDrawing.PlacesHSeparator (); + this.maximize_button = new Ctk.Image.from_filename (16, MAXIMIZE_ICON); + this.minimize_button = new Ctk.Image.from_filename (16, MINIMIZE_ICON); + + file_icon_array = new Gee.ArrayList<FileIcon> (); + for (int i = 0; i < 5; i++) + { + FileIcon file = new FileIcon (48, "Files", + FILES_FILE, + "Your files stored locally"); + this.file_icon_array.add (file); + this.add_actor (file.view); + this.add_actor (file.label); + } + + this.add_actor (this.Star); + this.add_actor (this.Separator); + this.add_actor (this.GroupName); + this.add_actor (this.maximize_button); + this.add_actor (this.minimize_button); + + this.is_open = true; + this.show_all (); + + this.maximize_button.set_reactive (true); + this.minimize_button.set_reactive (true); + this.maximize_button.hide(); + this.minimize_button.show(); + + this.maximize_button.button_release_event.connect (this.on_maximize); + this.minimize_button.button_release_event.connect (this.on_minimize); + + + } + + construct + { + } + + public bool on_minimize (Clutter.Event event) + { + this.maximize_button.show(); + this.minimize_button.hide(); + this.is_open = false; + return false; + } + + public bool on_maximize (Clutter.Event event) + { + this.maximize_button.hide(); + this.minimize_button.show(); + this.is_open = true; + return false; + } + } + + public class FileView : Ctk.Box + { + public FileGroup recent_file_group; + public FileGroup favourite_folder_group; + public FileGroup downloaded_file_group; + public override void allocate (Clutter.ActorBox box, + Clutter.AllocationFlags flags) + { + Clutter.ActorBox child_box = { 0.0f, 0.0f, 0.0f, 0.0f }; + float width, height; + float child_width, child_height; + + base.allocate (box, flags); + + width = box.x2 - box.x1; + height = box.y2 - box.y1; + + this.recent_file_group.get_preferred_width (height, + out child_width, + out child_width); + this.recent_file_group.get_preferred_height (width, + out child_height, + out child_height); + child_box.x1 = (width - child_width)/2.0f; + child_box.x2 = child_box.x1 + child_width; + child_box.y1 = 0.0f; + child_box.y2 = child_height; + recent_file_group.allocate (child_box, flags); + + child_box.y1 += child_height; + child_box.y2 = child_box.y1 + child_height; + favourite_folder_group.allocate (child_box, flags); + + child_box.y1 += child_height; + child_box.y2 = child_box.y1 + child_height; + downloaded_file_group.allocate (child_box, flags); + } + + public FileView () + { + recent_file_group = new FileGroup ("Recent Files"); + favourite_folder_group = new FileGroup ("Favourite Files"); + downloaded_file_group = new FileGroup ("Downloaded Files"); + + this.add_actor (recent_file_group); + this.add_actor (favourite_folder_group); + this.add_actor (downloaded_file_group); + this.show_all (); + } + + construct + { + } + } +} diff --git a/src/places/places-controller.vala b/src/places/places-controller.vala new file mode 100644 index 000000000..56fcaba62 --- /dev/null +++ b/src/places/places-controller.vala @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2009 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * 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/>. + * + * Authored by Neil Jagdish Patel <neil.patel@canonical.com> + * + */ + +using Gee; + +namespace Unity.Places +{ + public class Controller : Object + { + /** + * This class takes care of reading in the places, creating the view and + * keeping it up-to-date + **/ + public Shell shell { get; construct; } + private Model model; + private View view; + + public Controller (Shell shell) + { + Object (shell:shell); + } + + construct + { + this.model = new Model (); + this.view = new View (this.model); + + Idle.add (this.load_places); + } + + private bool load_places () + { + /* Currently we have a static list, in the future we'll be using the + * utility functions in libunity-places to load in the actual places + * information from the drive + */ + var homeplace = new HomePlace (); + homeplace.activated.connect (this.on_place_activated); + this.model.add (homeplace); + + var place = new FakePlace ("Applications", + PKGDATADIR + "/applications.png"); + place.activated.connect (this.on_place_activated); + this.model.add (place); + + place = new FakePlace ("Files & Folders", PKGDATADIR + "/files.png"); + place.activated.connect (this.on_place_activated); + this.model.add (place); + + return false; + } + + private void on_place_activated (Place place) + { + this.view.set_content_view (place.get_view ()); + } + + /* Public Methods */ + public View get_view () + { + return this.view; + } + } + + private class HomePlace : Place + { + public HomePlace () + { + Object (name:"Home", + icon_name:PKGDATADIR + "/home.png", + comment:""); + } + + public override Clutter.Actor get_view () + { + return new Default.View (); + } + } + + private class FakePlace : Place + { + public FakePlace (string name, string icon_name) + { + Object (name:name, icon_name:icon_name, comment:""); + } + + public override Clutter.Actor get_view () + { + if (this.name == "Applications") + return new Application.ApplicationView (); + + return new File.FileView (); + } + } +} + diff --git a/src/places/places-model.vala b/src/places/places-model.vala new file mode 100644 index 000000000..0d8502a68 --- /dev/null +++ b/src/places/places-model.vala @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * 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/>. + * + * Authored by Neil Jagdish Patel <neil.patel@canonical.com> + * + */ + +using Gee; + +namespace Unity.Places +{ + public class Model : Object + { + /** + * Contains a list of places + **/ + + /* Properties */ + public ArrayList<Place> list; + + /* Signals */ + public signal void place_added (Place place); + public signal void place_removed (Place place); + public signal void place_changed (Place place); + + public Model () + { + Object (); + } + + construct + { + list = new ArrayList<Place> (); + } + + public void add (Place place) + { + this.list.add (place); + + this.place_added (place); + } + + public void remove (Place place) + { + this.list.remove (place); + + this.place_removed (place); + } + + } +} + diff --git a/src/places/places-place.vala b/src/places/places-place.vala new file mode 100644 index 000000000..875f337cb --- /dev/null +++ b/src/places/places-place.vala @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * 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/>. + * + * Authored by Neil Jagdish Patel <neil.patel@canonical.com> + * + */ + +namespace Unity.Places +{ + public abstract class Place : Object + { + /** + * Represents a Place (icon, view etc). Will eventually be able to be + * constructed from a Unity.Place.Proxy as well as sub-classed + **/ + + /* Properties */ + public string name { get; construct; } + public string icon_name { get; construct; } + public string comment { get; construct; } + + private bool _active; + public bool active + { + get { return _active; } + set { if (_active != value) + { + _active = value; + if (_active) + this.activated (); + } + } + } + + /* Signals */ + public signal void activated (); + + public Place (string name, string icon_name) + { + Object (name:name, icon_name:icon_name); + } + + construct + { + _active = false; + } + + public abstract Clutter.Actor get_view (); + } +} + diff --git a/src/places/places-view.vala b/src/places/places-view.vala new file mode 100644 index 000000000..e26c11ffb --- /dev/null +++ b/src/places/places-view.vala @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2009 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * 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/>. + * + * Authored by Mirco "MacSlow" Müller <mirco.mueller@canonical.com> + * Neil Jagdish Patel <neil.patel@canonical.com> + * + */ + +namespace Unity.Places +{ + public class View : Ctk.Box + { + public Model model { get; construct; } + + private Bar.View bar_view; + private Clutter.Actor? content_view; + + public View (Model model) + { + Ctk.Padding padding = { 0.0f, 0.0f, 0.0f, 68.0f }; + + Object (model:model); + + this.orientation = Ctk.Orientation.VERTICAL; + + this.bar_view = new Bar.View (this.model); + this.bar_view.padding = padding; + this.add_actor (this.bar_view); + } + + public override void allocate (Clutter.ActorBox box, + Clutter.AllocationFlags flags) + { + Clutter.ActorBox child_box = { 0.0f, 0.0f, 0.0f, 0.0f }; + + child_box.x1 = 0; + child_box.x2 = box.x2 - box.x1; + child_box.y1 = 0; + child_box.y2 = 62; + + this.bar_view.allocate (child_box, flags); + + child_box.x1 = 58; + child_box.x2 = box.x2 - box.x1; + child_box.y1 = box.y1 + 62; + child_box.y2 = box.y2 - box.y1; + + if (this.content_view is Clutter.Actor) + { + this.content_view.allocate (child_box, flags); + } + } + + /* Public methods */ + public void set_content_view (Clutter.Actor actor) + { + if (this.content_view is Clutter.Actor) + { + this.content_view.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 300, + "opacity", 0, + "signal::completed", on_fade_out_done, + this.content_view); + } + + this.content_view = actor; + this.add_actor (this.content_view); + this.content_view.show (); + + actor.opacity = 0; + actor.animate (Clutter.AnimationMode.EASE_IN_QUAD, 300, + "opacity", 255); + } + + static void on_fade_out_done (Clutter.Animation anim, Clutter.Actor actor) + { + actor.destroy (); + } + } +} + diff --git a/src/quicklauncher/application-model.vala b/src/quicklauncher/application-model.vala index 5cdf3e7b5..0cba9b83c 100644 --- a/src/quicklauncher/application-model.vala +++ b/src/quicklauncher/application-model.vala @@ -23,19 +23,19 @@ namespace Unity.Quicklauncher.Models public class ApplicationShortcut : Object, ShortcutItem { public string exec; - public string name; + public string name; public string desktop_location; - + public string get_name () { return this.name; } - + public void activated () { debug ("activated %s - %s", this.name, this.exec); Gdk.AppLaunchContext context = new Gdk.AppLaunchContext (); - try + try { var desktop_file = new KeyFile (); desktop_file.load_from_file (this.desktop_location, 0); @@ -44,21 +44,21 @@ namespace Unity.Quicklauncher.Models appinfo.create_from_commandline (this.exec, this.name, 0); context.set_screen (Gdk.Display.get_default ().get_default_screen ()); context.set_timestamp (Gdk.CURRENT_TIME); - + appinfo.launch (null, context); } catch (Error e) { warning (e.message); } - + } } - - public class LibLauncherShortcut : Object, ShortcutItem + + public class LibLauncherShortcut : Object, ShortcutItem { public Launcher.Application app; public string name; - + public string get_name () { if (this.name == "") @@ -67,7 +67,7 @@ namespace Unity.Quicklauncher.Models } return this.name; } - + public void activated () { try @@ -79,13 +79,50 @@ namespace Unity.Quicklauncher.Models } } } - - public class ApplicationModel : Object, LauncherModel + + public class LauncherPinningShortcut : Object, ShortcutItem + { + public ApplicationModel app_model {get; construct;} + public string name { + get { + if (this.app_model.is_sticky) + { + return "Remove from Launcher"; + } + else + { + return "Add to Launcher"; + } + } + } + + public LauncherPinningShortcut (ApplicationModel model) + { + Object (app_model: model); + } + + construct + { + + } + + public string get_name () + { + return this.name; + } + + public void activated () + { + this.app_model.is_sticky = !this.app_model.is_sticky; + } + } + + public class ApplicationModel : Object, LauncherModel { private Gdk.Pixbuf _icon; private Launcher.Application app; private Launcher.Appman manager; - + public ApplicationModel (string desktop_uri) { this.manager = Launcher.Appman.get_default (); @@ -94,19 +131,20 @@ namespace Unity.Quicklauncher.Models this.app.notify["focused"].connect (this.notify_on_focused); this.app.notify["running"].connect (this.notify_on_running); - + this._icon = make_icon (app.icon_name); } - + construct { } - - private void on_app_opened (Wnck.Application app) + + private void on_app_opened (Wnck.Application app) { + this.activated (); this.request_attention (); } - + private void notify_on_focused () { if (app.focused) { @@ -115,37 +153,37 @@ namespace Unity.Quicklauncher.Models notify_focused(); } - private void notify_on_running () + private void notify_on_running () { - notify_active (); + notify_active (); } - public bool is_active + public bool is_active { get { return this.app.running; } } - public bool is_focused + public bool is_focused { get { return this.app.focused; } } - public Gdk.Pixbuf icon + public Gdk.Pixbuf icon { get { return _icon; } } - public string name + public string name { get { return this.app.name; } } - + private bool _is_sticky; - public bool is_sticky + public bool is_sticky { get { return _is_sticky; } - set - { + set + { var favorites = Launcher.Favorites.get_default (); string uid = get_fav_uid (); - if (uid != "" && !value) + if (uid != "" && !value) { // we are a favorite and we need to be unfavorited favorites.remove_favorite (uid); @@ -179,7 +217,7 @@ namespace Unity.Quicklauncher.Models e.message); return ret_list; } - + var groups = desktop_file.get_groups (); for (int a = 0; a < groups.length; a++) { @@ -188,7 +226,7 @@ namespace Unity.Quicklauncher.Models string exec = ""; string name = ""; try - { + { exec = desktop_file.get_value (groups[a], "Exec"); name = desktop_file.get_locale_string (groups[a], "Name", ""); } catch (Error e) @@ -205,16 +243,19 @@ namespace Unity.Quicklauncher.Models } return ret_list; } - + public Gee.ArrayList<ShortcutItem> get_menu_shortcut_actions () { Gee.ArrayList<ShortcutItem> ret_list = new Gee.ArrayList<ShortcutItem> (); - + var open_entry = new LibLauncherShortcut (); open_entry.app = this.app; open_entry.name = "Open.."; ret_list.add (open_entry); - + + var pin_entry = new LauncherPinningShortcut (this); + ret_list.add (pin_entry); + return ret_list; } @@ -225,21 +266,21 @@ namespace Unity.Quicklauncher.Models // we only want to switch to the application, not launch it app.show (); } - else + else { try { app.launch (); - } + } catch (GLib.Error e) { - critical ("could not launch application %s: %s", - this.app.name, + critical ("could not launch application %s: %s", + this.app.name, e.message); } } } - + /** * gets the favorite uid for this desktop file */ @@ -251,11 +292,11 @@ namespace Unity.Quicklauncher.Models unowned SList<string> favorite_list = favorites.get_favorites(); foreach (weak string uid in favorite_list) { - // we only want favorite *applications* for the moment + // we only want favorite *applications* for the moment var type = favorites.get_string(uid, "type"); if (type != "application") continue; - + string desktop_file = favorites.get_string(uid, "desktop_file"); if (desktop_file == my_desktop_path) { @@ -264,28 +305,28 @@ namespace Unity.Quicklauncher.Models } return myuid; } - - /** + + /** * taken from the prototype code and shamelessly stolen from * netbook launcher. needs to be improved at some point to deal * with all cases, it will miss some apps at the moment */ - static Gdk.Pixbuf make_icon(string? icon_name) + static Gdk.Pixbuf make_icon(string? icon_name) { /* - * This code somehow manages to miss a lot of icon names + * This code somehow manages to miss a lot of icon names * (non found icons are replaced with stock missing image icons) * which is a little strange as I ported this code fron netbook launcher * pixbuf-cache.c i think, If anyone else has a better idea for this then - * please give it a go. otherwise i will revisit this code the last week + * please give it a go. otherwise i will revisit this code the last week * of the month sprint */ Gdk.Pixbuf pixbuf = null; Gtk.IconTheme theme = Gtk.IconTheme.get_default (); - + if (icon_name == null) { - try + try { pixbuf = theme.load_icon(Gtk.STOCK_MISSING_IMAGE, 42, 0); } @@ -297,25 +338,25 @@ namespace Unity.Quicklauncher.Models return pixbuf; } - - if (icon_name.has_prefix("file://")) + + if (icon_name.has_prefix("file://")) { string filename = ""; - /* this try/catch sort of isn't needed... but it makes valac stop + /* this try/catch sort of isn't needed... but it makes valac stop * printing warning messages */ - try + try { filename = Filename.from_uri(icon_name); - } + } catch (GLib.ConvertError e) { } - if (filename != "") + if (filename != "") { try { - pixbuf = new Gdk.Pixbuf.from_file_at_scale(icon_name, + pixbuf = new Gdk.Pixbuf.from_file_at_scale(icon_name, 42, 42, true); } catch (Error e) @@ -328,14 +369,14 @@ namespace Unity.Quicklauncher.Models return pixbuf; } } - + if (Path.is_absolute(icon_name)) { - if (FileUtils.test(icon_name, FileTest.EXISTS)) + if (FileUtils.test(icon_name, FileTest.EXISTS)) { try { - pixbuf = new Gdk.Pixbuf.from_file_at_scale(icon_name, + pixbuf = new Gdk.Pixbuf.from_file_at_scale(icon_name, 42, 42, true); } catch (Error e) @@ -350,7 +391,7 @@ namespace Unity.Quicklauncher.Models } } - if (FileUtils.test ("/usr/share/pixmaps/" + icon_name, + if (FileUtils.test ("/usr/share/pixmaps/" + icon_name, FileTest.IS_REGULAR)) { try @@ -364,20 +405,20 @@ namespace Unity.Quicklauncher.Models "/usr/share/pixmaps/" + icon_name, e.message); } - + if (pixbuf is Gdk.Pixbuf) return pixbuf; } - + Gtk.IconInfo info = theme.lookup_icon(icon_name, 42, 0); - if (info != null) + if (info != null) { string filename = info.get_filename(); - if (FileUtils.test(filename, FileTest.EXISTS)) + if (FileUtils.test(filename, FileTest.EXISTS)) { try { - pixbuf = new Gdk.Pixbuf.from_file_at_scale(filename, + pixbuf = new Gdk.Pixbuf.from_file_at_scale(filename, 42, 42, true); } catch (Error e) @@ -386,17 +427,17 @@ namespace Unity.Quicklauncher.Models filename, e.message); } - + if (pixbuf is Gdk.Pixbuf) return pixbuf; } } - - try + + try { pixbuf = theme.load_icon(icon_name, 42, Gtk.IconLookupFlags.FORCE_SVG); } - catch (GLib.Error e) + catch (GLib.Error e) { warning ("could not load icon for %s - %s", icon_name, e.message); try @@ -410,7 +451,7 @@ namespace Unity.Quicklauncher.Models return pixbuf; } return pixbuf; - + } } } diff --git a/src/quicklauncher/launcher-model.vala b/src/quicklauncher/launcher-model.vala index 6287ec7da..9eeaaadc4 100644 --- a/src/quicklauncher/launcher-model.vala +++ b/src/quicklauncher/launcher-model.vala @@ -20,20 +20,21 @@ namespace Unity.Quicklauncher.Models { - - public interface LauncherModel : GLib.Object + + public interface LauncherModel : GLib.Object { public abstract bool is_active {get;} public abstract bool is_focused {get;} public abstract Gdk.Pixbuf icon {get;} public abstract bool is_sticky {get; set;} - + public abstract string name {get;} - + public abstract signal void notify_active (); public abstract signal void notify_focused (); public abstract signal void request_attention (); - + public abstract signal void activated (); + public abstract Gee.ArrayList<ShortcutItem> get_menu_shortcuts (); public abstract Gee.ArrayList<ShortcutItem> get_menu_shortcut_actions (); @@ -43,7 +44,7 @@ namespace Unity.Quicklauncher.Models public interface ShortcutItem : GLib.Object { public abstract string get_name (); - + public abstract void activated (); } diff --git a/src/quicklauncher/launcher-view.vala b/src/quicklauncher/launcher-view.vala index 4000b9057..34d9bcb21 100644 --- a/src/quicklauncher/launcher-view.vala +++ b/src/quicklauncher/launcher-view.vala @@ -21,12 +21,10 @@ using Unity.Quicklauncher.Models; namespace Unity.Quicklauncher { - const string THROBBER_FILE = Unity.PKGDATADIR - + "/quicklauncher_spinner.png"; const string FOCUSED_FILE = Unity.PKGDATADIR - + "/quicklauncher_focused_indicator.svg"; + + "/quicklauncher_focused_indicator.png"; const string RUNNING_FILE = Unity.PKGDATADIR - + "/quicklauncher_running_indicator.svg"; + + "/quicklauncher_running_indicator.png"; const string HONEYCOMB_MASK_FILE = Unity.PKGDATADIR + "/honeycomb-mask.png"; const string MENU_BG_FILE = Unity.PKGDATADIR @@ -36,7 +34,6 @@ namespace Unity.Quicklauncher const uint MEDIUM_DELAY = 800; const uint LONG_DELAY = 1600; - public class LauncherView : Ctk.Bin { @@ -44,19 +41,17 @@ namespace Unity.Quicklauncher /* the prettys */ private Ctk.Image icon; - private Ctk.Image throbber; - private Ctk.Image focused_indicator; - private Ctk.Image running_indicator; + private Clutter.Texture focused_indicator; + private Clutter.Texture running_indicator; private Gdk.Pixbuf honeycomb_mask; private Clutter.Group container; - private Ctk.Menu menu; - private Ctk.EffectDropShadow menu_dropshadow; private Gee.ArrayList<ShortcutItem> offline_shortcuts; private Gee.ArrayList<ShortcutItem> shortcut_actions; + private QuicklistController? quicklist_controller; + private Ctk.EffectGlow effect_icon_glow; - private Ctk.EffectDropShadow effect_icon_dropshadow; /* internal view logic datatypes */ private uint32 last_pressed_time; @@ -86,7 +81,6 @@ namespace Unity.Quicklauncher public signal void request_attention (); public signal void clicked (); - /* animations */ private Clutter.Animation anim_throbber; @@ -102,8 +96,6 @@ namespace Unity.Quicklauncher } } - private Clutter.Animation hover_anim; - /* constructors */ public LauncherView (LauncherModel model) { @@ -111,6 +103,8 @@ namespace Unity.Quicklauncher this.model = model; this.model.notify_active.connect (this.notify_on_is_running); this.model.notify_focused.connect (this.notify_on_is_focused); + this.model.activated.connect (this.on_activated); + this.name = "Unity.Quicklauncher.LauncherView-" + this.model.name; notify_on_is_running (); notify_on_is_focused (); @@ -143,28 +137,33 @@ namespace Unity.Quicklauncher this.clicked.connect (this.on_clicked); this.icon.do_queue_redraw (); - effect_icon_dropshadow = new Ctk.EffectDropShadow(3, 5, 5); - this.icon.add_effect(effect_icon_dropshadow); - set_reactive (true); + this.quicklist_controller = null; } private void load_textures () { - this.throbber = new Ctk.Image.from_filename (20, THROBBER_FILE); - this.throbber.set_z_rotation_from_gravity (0.0f, - Clutter.Gravity.CENTER); - this.container.add_actor (this.throbber); - - this.focused_indicator = new Ctk.Image.from_filename (8, - FOCUSED_FILE); + try + { + this.focused_indicator = new Clutter.Texture (); + this.focused_indicator.set_from_file (FOCUSED_FILE); + } catch (Error e) + { + this.focused_indicator = new Clutter.Texture (); + warning ("loading focused indicator failed, %s", e.message); + } this.container.add_actor (this.focused_indicator); - this.running_indicator = new Ctk.Image.from_filename (8, - RUNNING_FILE); + try + { + this.running_indicator = new Clutter.Texture (); + this.running_indicator.set_from_file (RUNNING_FILE); + } catch (Error e) + { + this.running_indicator = new Clutter.Texture (); + warning ("loading running indicator failed, %s", e.message); + } this.container.add_actor (this.running_indicator); - - this.throbber.set_opacity (0); this.focused_indicator.set_opacity (0); this.running_indicator.set_opacity (0); @@ -183,18 +182,15 @@ namespace Unity.Quicklauncher } /** - * re-layouts the various indicators and throbbers in out view + * re-layouts the various indicators */ private void relayout () { - this.throbber.set_position (container.width - this.throbber.width, - container.height - this.throbber.height); - float mid_point_y = this.container.height / 2.0f; float focus_halfy = this.focused_indicator.height / 2.0f; - float focus_halfx = container.width - this.focused_indicator.width; + float focus_halfx = container.width + this.focused_indicator.width + 2; - this.focused_indicator.set_position(focus_halfx + 12, + this.focused_indicator.set_position(focus_halfx, mid_point_y - focus_halfy); this.running_indicator.set_position (0, mid_point_y - focus_halfy); @@ -204,73 +200,84 @@ namespace Unity.Quicklauncher /* animation logic */ private void throbber_start () { - if (anim_throbber != null) - anim_throbber.completed (); - - this.throbber.opacity = 255; - this.throbber.set_z_rotation_from_gravity (0.0f, - Clutter.Gravity.CENTER); - this.anim_throbber = this.throbber.animate ( - Clutter.AnimationMode.LINEAR, LONG_DELAY, - "rotation-angle-z", 360.0f - ); - - this.anim_throbber.loop = true; - GLib.Timeout.add_seconds (8, on_launch_timeout); - } - private void throbber_fadeout () - { - if (this.throbber.opacity == 0) - return; + effect_icon_glow = new Ctk.EffectGlow (); + Clutter.Color c = Clutter.Color () { + red = 255, + green = 255, + blue = 255, + alpha = 255 + }; + effect_icon_glow.set_background_texture (honeycomb_mask); + effect_icon_glow.set_color (c); + effect_icon_glow.set_opacity (0.0f); + this.icon.add_effect (effect_icon_glow); + this.icon.do_queue_redraw (); - if (anim_throbber != null) - anim_throbber.completed (); + this.anim_throbber = effect_icon_glow.animate ( + Clutter.AnimationMode.EASE_IN_OUT_SINE, SHORT_DELAY, + "opacity", 1.0f); + this.effect_icon_glow.set_margin (6); - this.anim_throbber = - this.throbber.animate (Clutter.AnimationMode.EASE_IN_QUAD, - SHORT_DELAY, - "opacity", - 0); - this.anim_throbber.loop = false; + Signal.connect_after (this.anim_throbber, "completed", + (Callback)do_anim_throbber_loop, this); + + GLib.Timeout.add_seconds (8, on_launch_timeout); } - private void throbber_hide () + private static void do_anim_throbber_loop (Object sender, LauncherView self) + requires (self is LauncherView) { - if (this.throbber.opacity > 0) - throbber_fadeout (); + if (self.is_starting) + { + // we are still starting so do another loop + float factor = 0.0f; + if (self.effect_icon_glow.opacity < 0.5) + { + factor = 1.0f; + } + + self.anim_throbber = self.effect_icon_glow.animate ( + Clutter.AnimationMode.EASE_IN_OUT_SINE, + SHORT_DELAY, + "opacity", factor); + Signal.connect_after (self.anim_throbber, "completed", + (Callback)do_anim_throbber_loop, self); + } + else + { + // we should fadeout if we are too bright, otherwise remove effect + if (self.effect_icon_glow.opacity >= 0.1) + { + self.anim_throbber = self.effect_icon_glow.animate ( + Clutter.AnimationMode.EASE_IN_OUT_SINE, + SHORT_DELAY, + "opacity", 0.0); + } + else + { + self.icon.remove_effect (self.effect_icon_glow); + } + } } - - private void start_hover_anim () + private void throbber_fadeout () { - this.hover_anim = effect_icon_glow.animate ( - Clutter.AnimationMode.EASE_IN_OUT_SINE, SHORT_DELAY, - "factor", 1.0f); - this.hover_anim.completed.connect (on_hover_anim_completed); + return; } - private void on_hover_anim_completed () + private void throbber_hide () { - if (is_hovering) - { - Idle.add (do_new_hover_anim); - } + throbber_fadeout (); } - private bool do_new_hover_anim () - { - float fadeto = 0.0f; - if (effect_icon_glow.get_factor() <= 0.0f) - fadeto = 1.0f; - this.hover_anim = effect_icon_glow.animate( - Clutter.AnimationMode.EASE_IN_OUT_CIRC, 600, "factor", fadeto); - this.hover_anim.completed.connect (on_hover_anim_completed); - return false; + /* callbacks on model */ + private void on_activated () + { + this.is_starting = false; } - /* callbacks on model */ private void notify_on_icon () { if (this.model.icon is Gdk.Pixbuf) @@ -321,28 +328,21 @@ namespace Unity.Quicklauncher this.is_starting = false; } - - - /* callbacks on self */ - private bool on_mouse_enter (Clutter.Event event) { this.is_hovering = true; - effect_icon_glow = new Ctk.EffectGlow (); - Clutter.Color c = Clutter.Color () { - red = 255, - green = 255, - blue = 255, - alpha = 255 - }; - effect_icon_glow.set_background_texture (honeycomb_mask); - effect_icon_glow.set_color (c); - effect_icon_glow.set_factor (1.0f); - this.icon.add_effect (effect_icon_glow); - this.icon.do_queue_redraw (); - - start_hover_anim (); - + if (this.quicklist_controller == null) + { + this.quicklist_controller = new QuicklistController (this.model.name, + this, + this.get_stage () as Clutter.Stage + ); + this.build_quicklist (); + } + if (!this.quicklist_controller.is_label) + { + this.quicklist_controller.show_label (); + } return false; } @@ -355,14 +355,14 @@ namespace Unity.Quicklauncher private bool on_mouse_leave(Clutter.Event src) { - if (this.is_hovering) - { - this.is_hovering = false; - this.hover_anim.completed (); - this.icon.remove_effect(this.effect_icon_glow); - this.icon.queue_relayout(); - } - + this.is_hovering = false; + if (this.quicklist_controller is QuicklistController) + { + if (this.quicklist_controller.is_label) + { + this.quicklist_controller.close_menu (); + } + } return false; } @@ -375,92 +375,28 @@ namespace Unity.Quicklauncher } else { - build_quicklist (); + if (this.quicklist_controller.is_label) + { + this.quicklist_controller.show_menu (); + } } return false; } + /* menu handling */ private void build_quicklist () { this.offline_shortcuts = this.model.get_menu_shortcuts (); this.shortcut_actions = this.model.get_menu_shortcut_actions (); - - this.menu = new Ctk.Menu (); - Clutter.Stage stage = this.get_stage() as Clutter.Stage; - stage.add_actor (this.menu); - - float x, y; - this.get_transformed_position (out x, out y); - this.menu.attach_to_actor (this); - - Ctk.Padding padding = Ctk.Padding () { - left = 6, - right = 6, - top = 6, - bottom = 6 - }; - this.menu.set_padding (padding); - foreach (ShortcutItem shortcut in this.offline_shortcuts) { - Ctk.MenuItem menuitem = new Ctk.MenuItem.with_label ( - shortcut.get_name ()); - this.menu.append (menuitem); - menuitem.activated.connect (shortcut.activated); - menuitem.activated.connect (this.close_menu); + this.quicklist_controller.add_action (shortcut, true); } - // add a seperator and a menu label - var seperator = new Ctk.MenuSeperator (); - this.menu.append (seperator); - - var name_label = new Ctk.MenuItem.with_label (this.model.name); - this.menu.append (name_label); - name_label.set_reactive (false); - - seperator = new Ctk.MenuSeperator (); - this.menu.append (seperator); - - // parse the menu actions - foreach (ShortcutItem shortcut in this.shortcut_actions) { - Ctk.MenuItem menuitem = new Ctk.MenuItem.with_label ( - shortcut.get_name ()); - this.menu.append (menuitem); - menuitem.activated.connect (shortcut.activated); - menuitem.activated.connect (this.close_menu); - } - try { - var bg_tex = new Clutter.Texture.from_file (MENU_BG_FILE); - bg_tex.set_opacity (38); - - bg_tex.set_repeat (true, true); - this.menu.set_texture(bg_tex); - } catch (Error e) - { - critical (e.message); + this.quicklist_controller.add_action (shortcut, false); } - Clutter.Color color = Clutter.Color () - { - red = 0x00, - green = 0x00, - blue = 0x00, - alpha = (uint8) (0xFF * 0.30) - }; - this.menu.set_color (color); - - this.menu_dropshadow = new Ctk.EffectDropShadow(3, 5, 5); - this.menu.add_effect(this.menu_dropshadow); - this.menu.show (); - - } - - private void close_menu () - { - this.menu.remove_effect(this.menu_dropshadow); - Clutter.Stage stage = this.get_stage() as Clutter.Stage; - stage.remove_actor (this.menu); } private bool on_released (Clutter.Event src) diff --git a/src/quicklauncher/quicklauncher-manager.vala b/src/quicklauncher/quicklauncher-manager.vala index 99322b8f0..132d79146 100644 --- a/src/quicklauncher/quicklauncher-manager.vala +++ b/src/quicklauncher/quicklauncher-manager.vala @@ -63,6 +63,7 @@ namespace Unity.Quicklauncher private bool on_drag_drop (Ctk.Actor actor, Gdk.DragContext context, int x, int y, uint time_) { + debug ("on_drag_drop called"); if (context.targets != null) { Gdk.Atom target_type = (Gdk.Atom) context.targets.nth_data (Unity.dnd_targets.TARGET_URL); @@ -93,18 +94,20 @@ namespace Unity.Quicklauncher Gtk.SelectionData data, uint target_type, uint time_) { + debug ("on_drag_data_recieved called"); bool dnd_success = false; bool delete_selection_data = false; - debug ("got dnd data"); // Deal with what we are given from source if ((data != null) && (data.length >= 0)) { if (context.action == Gdk.DragAction.MOVE) { delete_selection_data = true; + debug ("delete_selection_data = true"); } switch (target_type) { case Unity.dnd_targets.TARGET_URL: // we got a uri, forward it to the uri handler + debug ("got a TARGET_URL"); dnd_success = handle_uri ((string) data.data); break; default: @@ -120,6 +123,7 @@ namespace Unity.Quicklauncher private bool handle_uri (string uri) { + debug ("handling uri: " + uri); string clean_uri = uri.split("\n", 2)[0].split("\r", 2)[0]; try { @@ -129,6 +133,8 @@ namespace Unity.Quicklauncher warning ("%s", e.message); } clean_uri.strip(); + + debug ("clean uri: " + clean_uri); var split_uri = clean_uri.split ("://", 2); if ("http" in split_uri[0]) @@ -154,6 +160,7 @@ namespace Unity.Quicklauncher var favorites = Launcher.Favorites.get_default (); string uid = "app-" + Path.get_basename (clean_uri); + debug ("adding to favourites: " + uid); favorites.set_string (uid, "type", "application"); favorites.set_string (uid, "desktop_file", split_uri[1]); favorites.add_favorite (uid); diff --git a/src/quicklauncher/quicklist-controller.vala b/src/quicklauncher/quicklist-controller.vala new file mode 100644 index 000000000..c6fa65499 --- /dev/null +++ b/src/quicklauncher/quicklist-controller.vala @@ -0,0 +1,158 @@ +/* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */ +/* + * Copyright (C) 2009 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * 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/>. + * + * Authored by Gordon Allott <gord.allott@canonical.com> + * + */ +using Unity.Quicklauncher.Models; + +namespace Unity.Quicklauncher +{ + public Ctk.Menu? active_menu = null; + + public class QuicklistController : Object + { + public string label; + public Ctk.Menu? menu; + private Ctk.Menu? old_menu; + private Clutter.Stage stage; + private Ctk.Actor attached_widget; + + public bool is_label = false; // in label mode, don't add items + private Gee.LinkedList<ShortcutItem> prefix_actions; + private Gee.LinkedList<ShortcutItem> append_actions; + + public QuicklistController (string label, Ctk.Actor attached_to, + Clutter.Stage stage) + { + this.label = label; + this.stage = stage; + this.menu = null; + this.prefix_actions = new Gee.LinkedList<ShortcutItem> (); + this.append_actions = new Gee.LinkedList<ShortcutItem> (); + this.attached_widget = attached_to; + } + + ~QuicklistController () + { + this.menu.fadeout_and_destroy (); + } + + construct + { + } + + public void add_action (ShortcutItem shortcut, bool is_secondary) + { + /* replace with Unity.Quicklauncher.MenuItem or something when we have + * that ready, needs an activated () signal + */ + if (is_secondary) + { + this.prefix_actions.add (shortcut); + } + else + { + this.append_actions.add (shortcut); + } + } + + private void build_menu () + { + this.menu = new QuicklistMenu () as Ctk.Menu; + Ctk.MenuItem menuitem = new Ctk.MenuItem.with_label (this.label); + this.menu.append (menuitem, true); + this.menu.attach_to_actor (this.attached_widget); + stage.add_actor (this.menu); + } + + public void show_label () + { + // first of all check, if we have a menu active we don't show any labels + if (Unity.Quicklauncher.active_menu != null) + { + return; + } + + if (this.menu == null) + { + this.build_menu (); + } + + this.menu.show(); + this.is_label = true; + } + + public void show_menu () + { + if (this.menu == null) + { + this.show_label (); + } + + if (Unity.Quicklauncher.active_menu != null) + { + // we already have an active menu, so destroy that and start this one + Unity.Quicklauncher.active_menu.fadeout_and_destroy (); + Unity.Quicklauncher.active_menu = null; + } + + this.is_label = false; + foreach (ShortcutItem shortcut in this.prefix_actions) + { + var label = shortcut.get_name (); + Ctk.MenuItem menuitem = new Ctk.MenuItem.with_label (label); + this.menu.prepend (menuitem, false); + menuitem.activated.connect (shortcut.activated); + menuitem.activated.connect (this.close_menu); + } + + foreach (ShortcutItem shortcut in this.append_actions) + { + var label = shortcut.get_name (); + Ctk.MenuItem menuitem = new Ctk.MenuItem.with_label (label); + this.menu.append (menuitem, false); + menuitem.activated.connect (shortcut.activated); + menuitem.activated.connect (this.close_menu); + } + + Unity.Quicklauncher.active_menu = this.menu; + this.menu.set_detect_clicks (true); + this.menu.closed.connect (this.on_menu_close); + this.is_label = false; + } + + private void on_menu_close () + { + if (Unity.Quicklauncher.active_menu == this.menu) + { + Unity.Quicklauncher.active_menu = null; + } + this.is_label = false; + this.old_menu = this.menu; + this.menu = null; + } + + public void close_menu () + { + this.menu.fadeout_and_destroy (); + this.old_menu = this.menu; + this.menu = null; + this.is_label = false; + } + + } +} diff --git a/src/quicklauncher/quicklist-view.vala b/src/quicklauncher/quicklist-view.vala new file mode 100644 index 000000000..db6109461 --- /dev/null +++ b/src/quicklauncher/quicklist-view.vala @@ -0,0 +1,48 @@ +/* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */ +/* + * Copyright (C) 2009 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * 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/>. + * + * Authored by Gordon Allott <gord.allott@canonical.com> + * + */ + +namespace Unity.Quicklauncher +{ + + /* we call this instead of Ctk.Menu so you can alter this to look right */ + public class QuicklistMenu : Ctk.Menu + { + Clutter.Rectangle ql_background; + construct + { + Clutter.Color color = Clutter.Color () { + red = 0x20, + green = 0x30, + blue = 0x40, + alpha = 0xff + }; + this.ql_background = new Clutter.Rectangle.with_color (color); + + this.set_background (this.ql_background); + Ctk.Padding padding = Ctk.Padding () { + left = 6, + right = 6, + top = 6, + bottom = 6 + }; + this.set_padding (padding); + } + } +} diff --git a/src/quicklauncher/unity-scroller.vala b/src/quicklauncher/unity-scroller.vala index 75b4bb92b..9c16e31a3 100644 --- a/src/quicklauncher/unity-scroller.vala +++ b/src/quicklauncher/unity-scroller.vala @@ -66,6 +66,8 @@ namespace Unity.Widgets public class Scroller : Ctk.Actor, Clutter.Container { + private uint drag_sensitivity = 3; + private float click_start_pos = 0; private float _drag_pos = -0.0f; public float drag_pos { get { return this._drag_pos; } @@ -141,8 +143,9 @@ namespace Unity.Widgets construct { try { - bgtex = new Clutter.Texture.from_file ( - Unity.PKGDATADIR + "/honeycomb.png"); + bgtex = new Clutter.Texture (); + bgtex.set_load_async (true); + bgtex.set_from_file (Unity.PKGDATADIR + "/honeycomb.png"); } catch (Error e) { @@ -152,8 +155,9 @@ namespace Unity.Widgets } try { - gradient = new Clutter.Texture.from_file ( - Unity.PKGDATADIR + "/gradient.png"); + gradient = new Clutter.Texture (); + gradient.set_load_async (true); + gradient.set_from_file (Unity.PKGDATADIR + "/gradient.png"); } catch (Error e) { @@ -238,13 +242,12 @@ namespace Unity.Widgets private void on_fling_frame (Clutter.Timeline timeline, int msecs) { - // the jist here is that we are doing a *real* per frame fling so we need + // the gist here is that we are doing a *real* per frame fling so we need // to head towards a given goal, bouncing around on the way float difference = this.drag_pos - this.fling_target; this.fling_velocity += difference * 0.005f; - if (difference < 1.0f && difference > -1.0f) { // we have arrived at our destination. @@ -332,6 +335,7 @@ namespace Unity.Widgets Clutter.ButtonEvent buttonevent = event.button; this.previous_y = buttonevent.y; this.last_drag_pos = (float)this.drag_pos; + this.click_start_pos = buttonevent.y; return true; } @@ -383,10 +387,14 @@ namespace Unity.Widgets this.scroll_anim.completed (); } - position = get_next_neg_position (position); - this.scroll_anim = this.animate ( + if (iters > 0) + { + + position = get_next_neg_position (position); + this.scroll_anim = this.animate ( Clutter.AnimationMode.EASE_OUT_QUAD, 16 * iters, "drag_pos", position); + } } return true; @@ -394,10 +402,17 @@ namespace Unity.Widgets private bool on_motion_event (Clutter.Event event) { - if (this.button_down) + if (this.button_down && this.is_dragging == false) { - this.is_dragging = true; + var diff = event.motion.y - this.click_start_pos; + if (diff > this.drag_sensitivity || -diff > this.drag_sensitivity) + { + this.is_dragging = true; + } + } + if (this.button_down && this.is_dragging) + { Clutter.grab_pointer (this); /* Disable any animations on the children */ @@ -620,8 +635,6 @@ namespace Unity.Widgets child.set_clip (0, 0, child_box.get_width (), child_box.get_height ()); } - - } /* also allocate our background graphics */ @@ -655,7 +668,6 @@ namespace Unity.Widgets { Clutter.Actor child = childcontainer.child; child.paint (); - child.pick (color); } } diff --git a/src/window.vala b/src/window.vala index 1842918ce..50a7ad915 100644 --- a/src/window.vala +++ b/src/window.vala @@ -26,7 +26,7 @@ namespace Unity public bool is_popup { get; construct; } public int popup_width { get; construct; } public int popup_height { get; construct; } - + private Wnck.Screen wnck_screen; private Workarea workarea_size; @@ -36,27 +36,29 @@ namespace Unity private Background background; private Quicklauncher.View quicklauncher; - private Places.View places; private Panel.View panel; + private Places.Controller controller; + private Unity.Places.View places; + public UnderlayWindow (bool popup, int width, int height) { Object(is_popup: popup, popup_width: width, popup_height: height); } - + construct { START_FUNCTION (); this.workarea_size = new Workarea (); this.workarea_size.update_net_workarea (); - + if (this.is_popup) { this.type_hint = Gdk.WindowTypeHint.NORMAL; this.decorated = true; this.skip_taskbar_hint = false; this.skip_pager_hint = false; - this.delete_event.connect (() => + this.delete_event.connect (() => { Gtk.main_quit (); return false; @@ -73,7 +75,7 @@ namespace Unity this.accept_focus = false; this.can_focus = false; this.delete_event.connect (() => { return true; }); - this.screen.size_changed.connect ((s) => + this.screen.size_changed.connect ((s) => { this.relayout (); }); this.screen.monitors_changed.connect ((s) => { this.relayout (); }); @@ -81,14 +83,17 @@ namespace Unity this.title = "Unity"; this.icon_name = "distributor-logo"; this.is_showing = false; - + /* Gtk.ClutterEmbed */ + LOGGER_START_PROCESS ("unity_underlay_window_realize"); this.realize (); + LOGGER_END_PROCESS ("unity_underlay_window_realize"); this.gtk_clutter = new GtkClutter.Embed (); this.add (this.gtk_clutter); + LOGGER_START_PROCESS ("gtk_clutter_realize"); this.gtk_clutter.realize (); - + LOGGER_END_PROCESS ("gtk_clutter_realize"); //setup dnd Gtk.TargetEntry[] target_list = { Gtk.TargetEntry () {target="STRING", flags=0, info=Unity.dnd_targets.TARGET_STRING }, @@ -99,15 +104,17 @@ namespace Unity Gtk.TargetEntry () {target="_NETSCAPE_URL", flags=0, info=Unity.dnd_targets.TARGET_URL } }; + LOGGER_START_PROCESS ("ctk_dnd_init"); Ctk.dnd_init (this.gtk_clutter, target_list); - + LOGGER_END_PROCESS ("ctk_dnd_init"); + this.stage = (Clutter.Stage)this.gtk_clutter.get_stage (); - - Clutter.Color stage_bg = Clutter.Color () { + + Clutter.Color stage_bg = Clutter.Color () { red = 0x00, green = 0x00, blue = 0x00, - alpha = 0xff + alpha = 0xff }; this.stage.set_color (stage_bg); this.stage.button_press_event.connect (this.on_stage_button_press); @@ -118,14 +125,16 @@ namespace Unity this.background.show (); this.quicklauncher = new Quicklauncher.View (this); - this.places = new Unity.Places.View (); + + this.controller = new Places.Controller (this); + this.places = this.controller.get_view (); this.stage.add_actor (this.quicklauncher); this.stage.add_actor (this.places); this.panel = new Panel.View (this); this.stage.add_actor (this.panel); this.panel.show (); - + /* Layout everything */ this.move (0, 0); this.relayout (); @@ -145,7 +154,7 @@ namespace Unity private void relayout () { int x, y, width, height; - + float ql_width; if (this.is_popup) { x = 0; @@ -164,26 +173,24 @@ namespace Unity height = size.height; } + ql_width = this.quicklauncher.get_width (); this.resize (width, height); this.stage.set_size (width, height); if (!this.is_popup) - Utils.set_strut ((Gtk.Window)this, 54, 0, height); + Utils.set_strut ((Gtk.Window)this, (uint)(ql_width), 0, height); /* Update component layouts */ this.background.set_position (0, 0); this.background.set_size (width, height); - - this.quicklauncher.set_size (58, height); + + + this.quicklauncher.set_size (ql_width, height); this.quicklauncher.set_position (this.workarea_size.left, this.workarea_size.top); - this.places.set_size (width - - this.workarea_size.left - - this.workarea_size.right, - height - - this.workarea_size.top - - this.workarea_size.bottom); + this.places.set_size (width, + height); this.places.set_position (0, 0); this.panel.set_size (width, 23); @@ -205,9 +212,9 @@ namespace Unity Wnck.Window new_window = this.wnck_screen.get_active_window (); if (new_window == null) return; - + /* FIXME: We want the second check to be a class_name or pid check */ - if (new_window is Wnck.Window + if (new_window is Wnck.Window && new_window.get_type () != Wnck.WindowType.DESKTOP && new_window.get_name () == "Unity") { @@ -259,26 +266,26 @@ namespace Unity } } - - public class Workarea + + public class Workarea { public signal void workarea_changed (); public int left; public int top; public int right; public int bottom; - + public Workarea () { left = 0; right = 0; top = 0; bottom = 0; - + update_net_workarea (); } - public void update_net_workarea () + public void update_net_workarea () { /* FIXME - steal code from the old liblauncher to do this * (launcher-session.c) this is just fake code to get it running @@ -288,5 +295,5 @@ namespace Unity top = 24; bottom = 0; } - } + } } |
