Compare commits
	
		
			33 Commits
		
	
	
		
			wip/fmuell
			...
			nbtk-intro
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 4f070317d2 | ||
|   | 661100abe8 | ||
|   | 3e90b11cfb | ||
|   | 4b4a1be420 | ||
|   | 1a4861ec4f | ||
|   | 2ac82da232 | ||
|   | 8f7e6f8117 | ||
|   | d2b98701be | ||
|   | faeda5dc8b | ||
|   | 70cb8e180b | ||
|   | 2232a92ba8 | ||
|   | 4743a8e750 | ||
|   | e1390c7dd5 | ||
|   | 49ba54820c | ||
|   | 8ffa161a7f | ||
|   | 0eca3efcb0 | ||
|   | 9c3af62dc4 | ||
|   | db0c2b5959 | ||
|   | 98215f497d | ||
|   | 9dbafe156e | ||
|   | 277dd7106a | ||
|   | 431f299756 | ||
|   | d8d7f5f711 | ||
|   | a07af9fb14 | ||
|   | f1f11f1e76 | ||
|   | c60a6a49de | ||
|   | 6687054474 | ||
|   | 60819b3a79 | ||
|   | 3e265b4bc6 | ||
|   | e2aa2a00f0 | ||
|   | 1edc88a2bd | ||
|   | 271e4ca07e | ||
|   | 9f79296276 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -38,5 +38,7 @@ src/gnomeshell-taskpanel | ||||
| src/gnome-shell | ||||
| src/test-recorder | ||||
| src/test-recorder.ogg | ||||
| src/test-theme | ||||
| stamp-h1 | ||||
| tests/run-test.sh | ||||
| xmldocs.make | ||||
|   | ||||
							
								
								
									
										17
									
								
								Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								Makefile.am
									
									
									
									
									
								
							| @@ -1,13 +1,22 @@ | ||||
| SUBDIRS = data js src po | ||||
| SUBDIRS = data js src tests po | ||||
|  | ||||
| EXTRA_DIST =		\ | ||||
| 	.project	\ | ||||
| 	.settings | ||||
| 	.settings	\ | ||||
| 	autogen.sh | ||||
|  | ||||
| # These are files checked into Git that we don't want to distribute | ||||
| DIST_EXCLUDE =					\ | ||||
| 	.gitignore				\ | ||||
| 	gnome-shell.doap			\ | ||||
| 	MAINTAINERS				\ | ||||
| 	tools/build/* | ||||
|  | ||||
| distcheck-hook: | ||||
| 	@echo "Checking disted javascript against files in git" | ||||
| 	@echo "Checking disted files against files in git" | ||||
| 	@failed=false; \ | ||||
| 	for f in `cd $(srcdir) && git ls-files js` ; do \ | ||||
| 	exclude=`(for p in $(DIST_EXCLUDE) ; do echo --exclude=$$p ; done)`; \ | ||||
| 	for f in `cd $(srcdir) && git ls-files $$exclude` ; do \ | ||||
| 		if ! test -e $(distdir)/$$f ; then \ | ||||
| 			echo File missing from distribution: $$f ; \ | ||||
| 			failed=true ; \ | ||||
|   | ||||
| @@ -57,8 +57,10 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugin | ||||
|                                  gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0 | ||||
|                                  gobject-introspection-1.0 >= 0.6.5) | ||||
| PKG_CHECK_MODULES(TIDY, clutter-1.0) | ||||
| PKG_CHECK_MODULES(NBTK, clutter-1.0 gtk+-2.0 clutter-imcontext-0.1) | ||||
| PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0) | ||||
| PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0) | ||||
| PKG_CHECK_MODULES(TOOLKIT, clutter-1.0 libcroco-0.6) | ||||
| PKG_CHECK_MODULES(TRAY, gtk+-2.0) | ||||
|  | ||||
| MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin | ||||
| @@ -128,5 +130,6 @@ AC_OUTPUT([ | ||||
|   js/misc/Makefile | ||||
|   js/ui/Makefile | ||||
|   src/Makefile | ||||
|   tests/Makefile | ||||
|   po/Makefile.in | ||||
| ]) | ||||
|   | ||||
| @@ -12,18 +12,26 @@ gnome-shell.desktop.in: gnome-shell.desktop.in.in | ||||
| gnome-shell.desktop: gnome-shell.desktop.in | ||||
| 	$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@ | ||||
|  | ||||
| imagedir = $(pkgdatadir)/images | ||||
|  | ||||
| dist_image_DATA =		\ | ||||
| 	add-workspace.svg	\ | ||||
| 	app-well-glow.png	\ | ||||
|         back.svg                \ | ||||
| 	close.svg		\ | ||||
| 	close-black.svg       \ | ||||
| 	info.svg		\ | ||||
| 	magnifier.svg  \ | ||||
| imagesdir = $(pkgdatadir)/images | ||||
| dist_images_DATA =				\ | ||||
| 	add-workspace.svg			\ | ||||
| 	app-well-glow.png			\ | ||||
| 	back.svg				\ | ||||
| 	close.svg				\ | ||||
| 	close-black.svg				\ | ||||
| 	info.svg				\ | ||||
| 	magnifier.svg				\ | ||||
| 	remove-workspace.svg | ||||
|  | ||||
| themedir = $(pkgdatadir)/theme | ||||
| dist_theme_DATA =				\ | ||||
| 	theme/gnome-shell.css			\ | ||||
| 	theme/scroll-button-down.png		\ | ||||
| 	theme/scroll-button-down-hover.png	\ | ||||
| 	theme/scroll-button-up.png		\ | ||||
| 	theme/scroll-button-up-hover.png	\ | ||||
| 	theme/scroll-vhandle.png | ||||
|  | ||||
| schemadir  = @GCONF_SCHEMA_FILE_DIR@ | ||||
| schema_DATA = gnome-shell.schemas | ||||
|  | ||||
|   | ||||
							
								
								
									
										97
									
								
								data/theme/gnome-shell.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								data/theme/gnome-shell.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| /* Copyright 2009, Red Hat, Inc. | ||||
|  * | ||||
|  * Portions adapted from NBTK's data/style/default.css | ||||
|  *   Copyright 2009 Intel Corporation | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  */ | ||||
|  | ||||
| NbtkScrollBar | ||||
| { | ||||
|   background-color: #354761; | ||||
|   padding: 0px; | ||||
| } | ||||
|  | ||||
| NbtkScrollView | ||||
| { | ||||
|   scrollbar-width: 16px; | ||||
|   scrollbar-height: 16px; | ||||
| } | ||||
|  | ||||
| NbtkButton#up-stepper | ||||
| { | ||||
|   border-image: url("scroll-button-up.png") 5; | ||||
| } | ||||
|  | ||||
| NbtkButton#up-stepper:hover, | ||||
| NbtkButton#up-stepper:active | ||||
| { | ||||
|   border-image: url("scroll-button-up-hover.png") 5; | ||||
| } | ||||
|  | ||||
| NbtkButton#down-stepper | ||||
| { | ||||
|   border-image: url("scroll-button-down.png") 5; | ||||
| } | ||||
|  | ||||
| NbtkButton#down-stepper:hover, | ||||
| NbtkButton#down-stepper:active | ||||
| { | ||||
|   border-image: url("scroll-button-down-hover.png") 5; | ||||
| } | ||||
|  | ||||
| NbtkScrollBar NbtkButton#vhandle | ||||
| { | ||||
|   border-image: url("scroll-vhandle.png") 5; | ||||
| } | ||||
|  | ||||
| NbtkScrollBar NbtkButton#vhandle:hover | ||||
| { | ||||
|   border-image: url("scroll-vhandle.png") 5; | ||||
| } | ||||
|  | ||||
| /* LookingGlass */ | ||||
|  | ||||
| #LookingGlassDialog | ||||
| { | ||||
|   background-color: rgba(0,0,0,0.85); | ||||
|   spacing: 4px; | ||||
|   padding: 4px; | ||||
|   border: 1px solid rgba(0,0,172,0.85); | ||||
|   border-radius: 4px; | ||||
|  | ||||
|   color: #88ff66; | ||||
| } | ||||
|  | ||||
| #LookingGlassDialog > #Toolbar | ||||
| { | ||||
|   border: 1px solid grey; | ||||
|   border-radius: 4px; | ||||
| } | ||||
|  | ||||
| #LookingGlassDialog NbtkLabel | ||||
| { | ||||
|   color: #88ff66; | ||||
| } | ||||
|  | ||||
| #LookingGlassDialog NbtkEntry | ||||
| { | ||||
|   color: #88ff66; | ||||
| } | ||||
|  | ||||
| #LookingGlassDialog NbtkBoxLayout#EvalBox | ||||
| { | ||||
|   padding: 4px; | ||||
|   spacing: 4px; | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-down-hover.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/theme/scroll-button-down-hover.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 225 B | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-down.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/theme/scroll-button-down.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 225 B | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-up-hover.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/theme/scroll-button-up-hover.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 211 B | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-up.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/theme/scroll-button-up.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 211 B | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-vhandle.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/theme/scroll-vhandle.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 323 B | 
| @@ -9,6 +9,7 @@ dist_jsui_DATA =		\ | ||||
| 	dash.js			\ | ||||
| 	dnd.js			\ | ||||
| 	docDisplay.js		\ | ||||
| 	environment.js		\ | ||||
| 	genericDisplay.js	\ | ||||
| 	link.js			\ | ||||
| 	lookingGlass.js		\ | ||||
|   | ||||
							
								
								
									
										32
									
								
								js/ui/environment.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								js/ui/environment.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Nbtk = imports.gi.Nbtk; | ||||
|  | ||||
| const Tweener = imports.ui.tweener; | ||||
|  | ||||
| // "monkey patch" in some varargs ClutterContainer methods; we need | ||||
| // to do this per-container class since there is no representation | ||||
| // of interfaces in Javascript | ||||
| function _patchContainerClass(containerClass) { | ||||
|     // This one is a straightforward mapping of the C method | ||||
|     containerClass.prototype.child_set = function(actor, props) { | ||||
|         let meta = this.get_child_meta(actor); | ||||
|         for (prop in props) | ||||
|             meta[prop] = props[prop]; | ||||
|     }; | ||||
|  | ||||
|     // clutter_container_add() actually is a an add-many-actors | ||||
|     // method. We conveniently, but somewhat dubiously, take the | ||||
|     // this opportunity to make it do something more useful. | ||||
|     containerClass.prototype.add = function(actor, props) { | ||||
|         this.add_actor(actor); | ||||
|         if (props) | ||||
|             this.child_set(actor, props); | ||||
|     }; | ||||
| } | ||||
|  | ||||
| _patchContainerClass(Nbtk.BoxLayout); | ||||
|  | ||||
| function init() { | ||||
|     Tweener.init(); | ||||
| } | ||||
| @@ -4,6 +4,7 @@ const Big = imports.gi.Big; | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Gio = imports.gi.Gio; | ||||
| const Pango = imports.gi.Pango; | ||||
| const Nbtk = imports.gi.Nbtk; | ||||
| const Shell = imports.gi.Shell; | ||||
| const Signals = imports.signals; | ||||
| const Lang = imports.lang; | ||||
| @@ -12,18 +13,7 @@ const Mainloop = imports.mainloop; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const Main = imports.ui.main; | ||||
|  | ||||
| const LG_BORDER_COLOR = new Clutter.Color(); | ||||
| LG_BORDER_COLOR.from_pixel(0x0000aca0); | ||||
| const LG_BACKGROUND_COLOR = new Clutter.Color(); | ||||
| LG_BACKGROUND_COLOR.from_pixel(0x000000d5); | ||||
| const GREY = new Clutter.Color(); | ||||
| GREY.from_pixel(0xAFAFAFFF); | ||||
| const MATRIX_GREEN = new Clutter.Color(); | ||||
| MATRIX_GREEN.from_pixel(0x88ff66ff); | ||||
| // FIXME pull from GConf | ||||
| const MATRIX_FONT = 'Monospace 10'; | ||||
|  | ||||
|                     /* Imports...feel free to add here as needed */ | ||||
| /* Imports...feel free to add here as needed */ | ||||
| var commandHeader = "const Clutter = imports.gi.Clutter; " + | ||||
|                     "const GLib = imports.gi.GLib; " + | ||||
|                     "const Gtk = imports.gi.Gtk; " + | ||||
| @@ -47,7 +37,7 @@ function Notebook() { | ||||
|  | ||||
| Notebook.prototype = { | ||||
|     _init: function() { | ||||
|         this.actor = new Big.Box(); | ||||
|         this.actor = new Nbtk.BoxLayout({ vertical: true }); | ||||
|  | ||||
|         this.tabControls = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, | ||||
|                                          spacing: 4, padding: 2 }); | ||||
| @@ -58,21 +48,24 @@ Notebook.prototype = { | ||||
|  | ||||
|     appendPage: function(name, child) { | ||||
|         let labelOuterBox = new Big.Box({ padding: 2 }); | ||||
|         let labelBox = new Big.Box({ padding: 2, border_color: MATRIX_GREEN, | ||||
|                                      reactive: true }); | ||||
|         let labelBox = new Nbtk.BoxLayout({ reactive: true }); | ||||
|         labelOuterBox.append(labelBox, Big.BoxPackFlags.NONE); | ||||
|         let label = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                        font_name: MATRIX_FONT, | ||||
|                                        text: name }); | ||||
|         let label = new Nbtk.Label({ text: name }); | ||||
|         labelBox.connect('button-press-event', Lang.bind(this, function () { | ||||
|             this.selectChild(child); | ||||
|             return true; | ||||
|         })); | ||||
|         labelBox.append(label, Big.BoxPackFlags.EXPAND); | ||||
|         this._tabs.push([child, labelBox]); | ||||
|         child.hide(); | ||||
|         this.actor.append(child, Big.BoxPackFlags.EXPAND); | ||||
|         labelBox.add(label, { expand: true }); | ||||
|         this.tabControls.append(labelOuterBox, Big.BoxPackFlags.NONE); | ||||
|  | ||||
|         let scrollview = new Nbtk.ScrollView({ x_fill: true, y_fill: true }); | ||||
|         scrollview.get_hscroll_bar().hide(); | ||||
|         scrollview.add_actor(child); | ||||
|  | ||||
|         this._tabs.push([child, labelBox, scrollview]); | ||||
|         scrollview.hide(); | ||||
|         this.actor.add(scrollview, { expand: true }); | ||||
|  | ||||
|         if (this._selectedIndex == -1) | ||||
|             this.selectIndex(0); | ||||
|     }, | ||||
| @@ -80,10 +73,10 @@ Notebook.prototype = { | ||||
|     _unselect: function() { | ||||
|         if (this._selectedIndex < 0) | ||||
|             return; | ||||
|         let [child, labelBox] = this._tabs[this._selectedIndex]; | ||||
|         let [child, labelBox, scrollview] = this._tabs[this._selectedIndex]; | ||||
|         labelBox.padding = 2; | ||||
|         labelBox.border = 0; | ||||
|         child.hide(); | ||||
|         scrollview.hide(); | ||||
|         this._selectedIndex = -1; | ||||
|     }, | ||||
|  | ||||
| @@ -95,10 +88,10 @@ Notebook.prototype = { | ||||
|             this.emit('selection', null); | ||||
|             return; | ||||
|         } | ||||
|         let [child, labelBox] = this._tabs[index]; | ||||
|         let [child, labelBox, scrollview] = this._tabs[index]; | ||||
|         labelBox.padding = 1; | ||||
|         labelBox.border = 1; | ||||
|         child.show(); | ||||
|         scrollview.show(); | ||||
|         this._selectedIndex = index; | ||||
|         this.emit('selection', child); | ||||
|     }, | ||||
| @@ -108,7 +101,7 @@ Notebook.prototype = { | ||||
|             this.selectIndex(-1); | ||||
|         else { | ||||
|             for (let i = 0; i < this._tabs.length; i++) { | ||||
|                 let [tabChild, labelBox] = this._tabs[i]; | ||||
|                 let [tabChild, labelBox, scrollview] = this._tabs[i]; | ||||
|                 if (tabChild == child) { | ||||
|                     this.selectIndex(i); | ||||
|                     return; | ||||
| @@ -130,20 +123,19 @@ Result.prototype = { | ||||
|  | ||||
|         this.actor = new Big.Box(); | ||||
|  | ||||
|         let cmdTxt = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                         font_name: MATRIX_FONT, | ||||
|                                         ellipsize: Pango.EllipsizeMode.END, | ||||
|                                         text: command }); | ||||
|         let cmdTxt = new Nbtk.Label({ text: command }); | ||||
|         cmdTxt.ellipsize = Pango.EllipsizeMode.END; | ||||
|  | ||||
|         this.actor.append(cmdTxt, Big.BoxPackFlags.NONE); | ||||
|         let resultTxt = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                            font_name: MATRIX_FONT, | ||||
|                                            ellipsize: Pango.EllipsizeMode.END, | ||||
|                                            text: "r(" + index + ") = " + o }); | ||||
|         let resultTxt = new Nbtk.Label({ text: "r(" + index + ") = " + o }); | ||||
|         resultTxt.ellipsize = Pango.EllipsizeMode.END; | ||||
|  | ||||
|         this.actor.append(resultTxt, Big.BoxPackFlags.NONE); | ||||
|         let line = new Big.Box({ border_color: GREY, | ||||
|                                  border_bottom: 1, | ||||
|                                  height: 8 }); | ||||
|         this.actor.append(line, Big.BoxPackFlags.NONE); | ||||
|         let line = new Clutter.Rectangle({ name: "Separator", | ||||
|                                            height: 1 }); | ||||
|         let padBin = new Nbtk.Bin({ name: "Separator", x_fill: true, y_fill: true }); | ||||
|         padBin.add_actor(line); | ||||
|         this.actor.append(padBin, Big.BoxPackFlags.NONE); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -158,17 +150,14 @@ ActorHierarchy.prototype = { | ||||
|  | ||||
|         this._parentList = []; | ||||
|  | ||||
|         this.actor = new Big.Box({ spacing: 4, | ||||
|                                    border: 1, | ||||
|                                    padding: 4, | ||||
|                                    border_color: GREY }); | ||||
|         this.actor = new Nbtk.BoxLayout({ name: "ActorHierarchy", vertical: true }); | ||||
|     }, | ||||
|  | ||||
|     setTarget: function(actor) { | ||||
|         this._previousTarget = this._target; | ||||
|         this.target = actor; | ||||
|  | ||||
|         this.actor.remove_all(); | ||||
|         this.actor.get_children().forEach(function (child) { child.destroy(); }); | ||||
|  | ||||
|         if (!(actor instanceof Clutter.Actor)) | ||||
|             return; | ||||
| @@ -181,11 +170,9 @@ ActorHierarchy.prototype = { | ||||
|         while ((parent = parent.get_parent()) != null) { | ||||
|             this._parentList.push(parent); | ||||
|  | ||||
|             let link = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                           font_name: MATRIX_FONT, | ||||
|                                           reactive: true, | ||||
|                                           text: "" + parent }); | ||||
|             this.actor.append(link, Big.BoxPackFlags.IF_FITS); | ||||
|             let link = new Nbtk.Label({ reactive: true, | ||||
|                                         text: "" + parent }); | ||||
|             this.actor.add_actor(link); | ||||
|             let parentTarget = parent; | ||||
|             link.connect('button-press-event', Lang.bind(this, function () { | ||||
|                 this._selectByActor(parentTarget); | ||||
| @@ -214,16 +201,13 @@ PropertyInspector.prototype = { | ||||
|  | ||||
|         this._parentList = []; | ||||
|  | ||||
|         this.actor = new Big.Box({ spacing: 4, | ||||
|                                    border: 1, | ||||
|                                    padding: 4, | ||||
|                                    border_color: GREY }); | ||||
|         this.actor = new Nbtk.BoxLayout({ name: "PropertyInspector", vertical: true }); | ||||
|     }, | ||||
|  | ||||
|     setTarget: function(actor) { | ||||
|         this.target = actor; | ||||
|  | ||||
|         this.actor.remove_all(); | ||||
|         this.actor.get_children().forEach(function (child) { child.destroy(); }); | ||||
|  | ||||
|         for (let propName in actor) { | ||||
|             let valueStr; | ||||
| @@ -233,11 +217,9 @@ PropertyInspector.prototype = { | ||||
|                 valueStr = '<error>'; | ||||
|             } | ||||
|             let propText = propName + ": " + valueStr; | ||||
|             let propDisplay = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                                  font_name: MATRIX_FONT, | ||||
|                                                  reactive: true, | ||||
|                                                  text: propText }); | ||||
|             this.actor.append(propDisplay, Big.BoxPackFlags.IF_FITS); | ||||
|             let propDisplay = new Nbtk.Label({ reactive: true, | ||||
|                                                text: propText }); | ||||
|             this.actor.add_actor(propDisplay); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -249,20 +231,16 @@ function Inspector() { | ||||
| Inspector.prototype = { | ||||
|     _init: function() { | ||||
|         let width = 150; | ||||
|         let eventHandler = new Big.Box({ background_color: LG_BACKGROUND_COLOR, | ||||
|                                          border: 1, | ||||
|                                          border_color: LG_BORDER_COLOR, | ||||
|                                          corner_radius: 4, | ||||
|                                          y: global.stage.height/2, | ||||
|                                          reactive: true | ||||
|                                       }); | ||||
|         let eventHandler = new Nbtk.BoxLayout({ name: "LookingGlassDialog", | ||||
|                                                 vertical: false, | ||||
|                                                 y: Math.floor(global.stage.height/2), | ||||
|                                                 reactive: true }); | ||||
|         eventHandler.connect('notify::allocation', Lang.bind(this, function () { | ||||
|             eventHandler.x = Math.floor((global.stage.width)/2 - (eventHandler.width)/2); | ||||
|         })); | ||||
|         global.stage.add_actor(eventHandler); | ||||
|         let displayText = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                              font_name: MATRIX_FONT, text: '' }); | ||||
|         eventHandler.append(displayText, Big.BoxPackFlags.EXPAND); | ||||
|         let displayText = new Nbtk.Label(); | ||||
|         eventHandler.add(displayText, { expand: true }); | ||||
|  | ||||
|         let borderPaintTarget = null; | ||||
|         let borderPaintId = null; | ||||
| @@ -321,29 +299,26 @@ LookingGlass.prototype = { | ||||
|         this._offset = 0; | ||||
|         this._results = []; | ||||
|  | ||||
|         // TODO replace with scrolling or something better | ||||
|         this._maxItems = 10; | ||||
|         // Sort of magic, but...eh. | ||||
|         this._maxItems = 150; | ||||
|  | ||||
|         this.actor = new Nbtk.BoxLayout({ name: "LookingGlassDialog", | ||||
|                                           vertical: true, | ||||
|                                           visible: false }); | ||||
|  | ||||
|         let gconf = Shell.GConf.get_default(); | ||||
|         gconf.watch_directory("/desktop/gnome/interface"); | ||||
|         gconf.connect("changed::/desktop/gnome/interface/monospace_font_name", | ||||
|                       Lang.bind(this, this._updateFont)); | ||||
|         this._updateFont(); | ||||
|  | ||||
|         this.actor = new Big.Box({ background_color: LG_BACKGROUND_COLOR, | ||||
|                                    border: 1, | ||||
|                                    border_color: LG_BORDER_COLOR, | ||||
|                                    corner_radius: 4, | ||||
|                                    padding_top: 8, | ||||
|                                    padding_left: 4, | ||||
|                                    padding_right: 4, | ||||
|                                    padding_bottom: 4, | ||||
|                                    spacing: 4, | ||||
|                                    visible: false | ||||
|                                 }); | ||||
|         global.stage.add_actor(this.actor); | ||||
|  | ||||
|         let toolbar = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, | ||||
|                                     border: 1, border_color: GREY, | ||||
|                                     corner_radius: 4 }); | ||||
|         this.actor.append(toolbar, Big.BoxPackFlags.NONE); | ||||
|         let toolbar = new Nbtk.BoxLayout({ name: "Toolbar" }); | ||||
|         this.actor.add_actor(toolbar); | ||||
|         let inspectIcon = Shell.TextureCache.get_default().load_gicon(new Gio.ThemedIcon({ name: 'gtk-color-picker' }), | ||||
|                                                                       24); | ||||
|         toolbar.append(inspectIcon, Big.BoxPackFlags.NONE); | ||||
|         toolbar.add_actor(inspectIcon); | ||||
|         inspectIcon.reactive = true; | ||||
|         inspectIcon.connect('button-press-event', Lang.bind(this, function () { | ||||
|             let inspector = new Inspector(); | ||||
| @@ -361,31 +336,26 @@ LookingGlass.prototype = { | ||||
|         })); | ||||
|  | ||||
|         let notebook = new Notebook(); | ||||
|         this.actor.append(notebook.actor, Big.BoxPackFlags.EXPAND); | ||||
|         toolbar.append(notebook.tabControls, Big.BoxPackFlags.END); | ||||
|         this.actor.add(notebook.actor, { expand: true }); | ||||
|  | ||||
|         this._evalBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, | ||||
|                                       spacing: 4 }); | ||||
|         let emptyBox = new Nbtk.Bin(); | ||||
|         toolbar.add(emptyBox, { expand: true }); | ||||
|         toolbar.add_actor(notebook.tabControls); | ||||
|  | ||||
|         this._evalBox = new Nbtk.BoxLayout({ name: "EvalBox", vertical: true }); | ||||
|         notebook.appendPage('Evaluator', this._evalBox); | ||||
|  | ||||
|         this._resultsArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, | ||||
|                                           spacing: 4 }); | ||||
|         this._evalBox.append(this._resultsArea, Big.BoxPackFlags.EXPAND); | ||||
|         this._evalBox.add(this._resultsArea, { expand: true }); | ||||
|  | ||||
|         let entryArea = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL }); | ||||
|         this._evalBox.append(entryArea, Big.BoxPackFlags.NONE); | ||||
|         this._evalBox.add_actor(entryArea); | ||||
|  | ||||
|         let label = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                        font_name: MATRIX_FONT, | ||||
|                                        text: 'js>>> ' }); | ||||
|         let label = new Nbtk.Label({ text: 'js>>> ' }); | ||||
|         entryArea.append(label, Big.BoxPackFlags.NONE); | ||||
|  | ||||
|         this._entry = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                          font_name: MATRIX_FONT, | ||||
|                                          editable: true, | ||||
|                                          activatable: true, | ||||
|                                          singleLineMode: true, | ||||
|                                          text: ''}); | ||||
|         this._entry = new Nbtk.Entry(); | ||||
|         /* unmapping the edit box will un-focus it, undo that */ | ||||
|         notebook.connect('selection', Lang.bind(this, function (nb, child) { | ||||
|             if (child == this._evalBox) | ||||
| @@ -403,7 +373,7 @@ LookingGlass.prototype = { | ||||
|             notebook.selectIndex(0); | ||||
|         })); | ||||
|  | ||||
|         this._entry.connect('activate', Lang.bind(this, function (o, e) { | ||||
|         this._entry.clutter_text.connect('activate', Lang.bind(this, function (o, e) { | ||||
|             let text = o.get_text(); | ||||
|             // Ensure we don't get newlines in the command; the history file is | ||||
|             // newline-separated. | ||||
| @@ -416,7 +386,7 @@ LookingGlass.prototype = { | ||||
|             this._historyNavIndex = -1; | ||||
|             return true; | ||||
|         })); | ||||
|         this._entry.connect('key-press-event', Lang.bind(this, function(o, e) { | ||||
|         this._entry.clutter_text.connect('key-press-event', Lang.bind(this, function(o, e) { | ||||
|             let symbol = e.get_key_symbol(); | ||||
|             if (symbol == Clutter.Escape) { | ||||
|                 this.close(); | ||||
| @@ -446,6 +416,19 @@ LookingGlass.prototype = { | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     _updateFont: function() { | ||||
|         let gconf = Shell.GConf.get_default(); | ||||
|         let fontName = gconf.get_string("/desktop/gnome/interface/monospace_font_name"); | ||||
|         // This is mishandled by the scanner - should by Pango.FontDescription_from_string(fontName); | ||||
|         // https://bugzilla.gnome.org/show_bug.cgi?id=595889 | ||||
|         let fontDesc = Pango.Font.description_from_string(fontName); | ||||
|         // We ignore everything but size and style; you'd be crazy to set your system-wide | ||||
|         // monospace font to be bold/oblique/etc. Could easily be added here. | ||||
|         this.actor.style = | ||||
|             'font-size: ' + fontDesc.get_size() / 1024. + (fontDesc.get_size_is_absolute() ? 'px' : 'pt') + ';' | ||||
|             + 'font-family: "' + fontDesc.get_family() + '";'; | ||||
|     }, | ||||
|  | ||||
|     _readHistory: function () { | ||||
|         if (!this._historyFile.query_exists(null)) | ||||
|             return; | ||||
|   | ||||
| @@ -7,16 +7,17 @@ const GLib = imports.gi.GLib; | ||||
| const Lang = imports.lang; | ||||
| const Mainloop = imports.mainloop; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Nbtk = imports.gi.Nbtk; | ||||
| const Shell = imports.gi.Shell; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const Chrome = imports.ui.chrome; | ||||
| const Environment = imports.ui.environment; | ||||
| const Overview = imports.ui.overview; | ||||
| const Panel = imports.ui.panel; | ||||
| const RunDialog = imports.ui.runDialog; | ||||
| const LookingGlass = imports.ui.lookingGlass; | ||||
| const Sidebar = imports.ui.sidebar; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const WindowManager = imports.ui.windowManager; | ||||
|  | ||||
| const DEFAULT_BACKGROUND_COLOR = new Clutter.Color(); | ||||
| @@ -43,7 +44,7 @@ function start() { | ||||
|  | ||||
|     global.grab_dbus_service(); | ||||
|  | ||||
|     Tweener.init(); | ||||
|     Environment.init(); | ||||
|  | ||||
|     // Ensure ShellAppMonitor is initialized; this will | ||||
|     // also initialize ShellAppSystem first.  ShellAppSystem | ||||
| @@ -66,6 +67,11 @@ function start() { | ||||
|     for (let i = 0; i < children.length; i++) | ||||
|         children[i].destroy(); | ||||
|  | ||||
|     let themeContext = Shell.ThemeContext.get_for_stage (global.stage); | ||||
|     let stylesheetPath = global.datadir + "/theme/gnome-shell.css"; | ||||
|     let theme = new Shell.Theme ({ application_stylesheet: stylesheetPath }); | ||||
|     themeContext.set_theme (theme); | ||||
|  | ||||
|     global.connect('panel-run-dialog', function(panel) { | ||||
|         // Make sure not more than one run dialog is shown. | ||||
|         getRunDialog().open(); | ||||
|   | ||||
							
								
								
									
										117
									
								
								src/Makefile-nbtk.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								src/Makefile-nbtk.am
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| nbtk_cflags =                    \ | ||||
|     -I$(top_srcdir)/src         \ | ||||
|     -DPREFIX=\""$(prefix)"\"        \ | ||||
|     -DLIBDIR=\""$(libdir)"\"        \ | ||||
|     -DG_DISABLE_DEPRECATED          \ | ||||
|     -DG_LOG_DOMAIN=\"Nbtk\"          \ | ||||
|     -DNBTK_COMPILATION  \ | ||||
|     $(NBTK_CFLAGS)           \ | ||||
|     $(NULL) | ||||
|  | ||||
| nbtk_built_sources = \ | ||||
|     nbtk-enum-types.h   \ | ||||
|     nbtk-enum-types.c   \ | ||||
|     nbtk-marshal.h      \ | ||||
|     nbtk-marshal.c | ||||
|  | ||||
| BUILT_SOURCES += $(nbtk_built_sources) | ||||
|  | ||||
| EXTRA_DIST += \ | ||||
| 	nbtk/nbtk-marshal.list \ | ||||
| 	nbtk/nbtk-enum-types.h.in \ | ||||
| 	nbtk/nbtk-enum-types.c.in | ||||
|  | ||||
| CLEANFILES += stamp-nbtk-marshal.h stamp-nbtk-enum-types.h | ||||
|  | ||||
| nbtk-marshal.h: stamp-nbtk-marshal.h | ||||
| 	@true | ||||
| stamp-nbtk-marshal.h: Makefile nbtk/nbtk-marshal.list | ||||
| 	$(AM_V_GEN) $(GLIB_GENMARSHAL) \ | ||||
| 		--prefix=_nbtk_marshal \ | ||||
| 		--header \ | ||||
| 	$(srcdir)/nbtk/nbtk-marshal.list > $@.tmp && \ | ||||
| 	(cmp -s $@.tmp nbtk-marshal.h || cp -f $@.tmp nbtk-marshal.h) && \ | ||||
| 	rm -f $@.tmp && \ | ||||
| 	echo timestamp > $(@F) | ||||
|  | ||||
| nbtk-marshal.c: Makefile nbtk/nbtk-marshal.list | ||||
| 	$(AM_V_GEN) (echo "#include \"nbtk-marshal.h\"" ; \ | ||||
| 	 $(GLIB_GENMARSHAL) \ | ||||
| 		--prefix=_nbtk_marshal \ | ||||
| 		--body \ | ||||
| 	 $(srcdir)/nbtk/nbtk-marshal.list ) > $@.tmp && \ | ||||
| 	cp -f $@.tmp nbtk-marshal.c && \ | ||||
| 	rm -f $@.tmp | ||||
|  | ||||
| nbtk-enum-types.h: stamp-nbtk-enum-types.h Makefile | ||||
| 	@true | ||||
| stamp-nbtk-enum-types.h: $(source_h) nbtk/nbtk-enum-types.h.in | ||||
| 	$(AM_V_GEN) ( cd $(srcdir) && \ | ||||
| 	  $(GLIB_MKENUMS) \ | ||||
| 	    --template nbtk/nbtk-enum-types.h.in \ | ||||
| 	  $(nbtk_source_h) ) >> $@.tmp && \ | ||||
| 	(cmp -s $@.tmp nbtk-enum-types.h || cp $@.tmp nbtk-enum-types.h) && \ | ||||
| 	rm -f $@.tmp && \ | ||||
| 	echo timestamp > $(@F) | ||||
|  | ||||
| nbtk-enum-types.c: stamp-nbtk-enum-types.h nbtk/nbtk-enum-types.c.in | ||||
| 	$(AM_V_GEN) ( cd $(srcdir) && \ | ||||
| 	  $(GLIB_MKENUMS) \ | ||||
| 	    --template nbtk/nbtk-enum-types.c.in \ | ||||
| 	  $(nbtk_source_h) ) >> $@.tmp && \ | ||||
| 	cp $@.tmp $@ && \ | ||||
| 	rm -f $@.tmp | ||||
|  | ||||
| # please, keep this sorted alphabetically | ||||
| nbtk_source_h =                  \ | ||||
|     nbtk/nbtk-adjustment.h            \ | ||||
|     nbtk/nbtk-bin.h                   \ | ||||
|     nbtk/nbtk-box-layout.h            \ | ||||
|     nbtk/nbtk-box-layout-child.h      \ | ||||
|     nbtk/nbtk-button.h                \ | ||||
|     nbtk/nbtk-clipboard.h             \ | ||||
|     nbtk/nbtk-entry.h                 \ | ||||
|     nbtk/nbtk-label.h                 \ | ||||
|     nbtk/nbtk-private.h               \ | ||||
|     nbtk/nbtk-scrollable.h            \ | ||||
|     nbtk/nbtk-scroll-bar.h            \ | ||||
|     nbtk/nbtk-scroll-view.h           \ | ||||
|     nbtk/nbtk-subtexture.h            \ | ||||
|     nbtk/nbtk-texture-cache.h         \ | ||||
|     nbtk/nbtk-texture-frame.h         \ | ||||
|     nbtk/nbtk-tooltip.h               \ | ||||
|     nbtk/nbtk-types.h                 \ | ||||
|     nbtk/nbtk-widget.h                \ | ||||
|     $(NULL) | ||||
|  | ||||
| # please, keep this sorted alphabetically | ||||
| nbtk_source_c =                  \ | ||||
|     nbtk/nbtk-adjustment.c           \ | ||||
|     nbtk/nbtk-bin.c                   \ | ||||
|     nbtk/nbtk-box-layout.c            \ | ||||
|     nbtk/nbtk-box-layout-child.c      \ | ||||
|     nbtk/nbtk-button.c                \ | ||||
|     nbtk/nbtk-clipboard.c             \ | ||||
|     nbtk/nbtk-entry.c                 \ | ||||
|     nbtk/nbtk-label.c                 \ | ||||
|     nbtk/nbtk-private.c               \ | ||||
|     nbtk/nbtk-scrollable.c            \ | ||||
|     nbtk/nbtk-scroll-bar.c            \ | ||||
|     nbtk/nbtk-scroll-view.c           \ | ||||
|     nbtk/nbtk-subtexture.c            \ | ||||
|     nbtk/nbtk-texture-cache.c         \ | ||||
|     nbtk/nbtk-texture-frame.c         \ | ||||
|     nbtk/nbtk-tooltip.c               \ | ||||
|     nbtk/nbtk-widget.c                \ | ||||
|     $(NULL) | ||||
|  | ||||
| noinst_LTLIBRARIES += libnbtk-1.0.la | ||||
|  | ||||
| libnbtk_1_0_la_LIBADD = $(NBTK_LIBS) | ||||
| libnbtk_1_0_la_SOURCES = \ | ||||
|     $(nbtk_source_c) \ | ||||
|     $(nbtk_source_h) \ | ||||
|     $(nbtk_built_sources) \ | ||||
|     $(NULL) | ||||
| libnbtk_1_0_la_CPPFLAGS = $(nbtk_cflags) | ||||
| libnbtk_1_0_la_LDFLAGS = $(LDADD) | ||||
							
								
								
									
										36
									
								
								src/Makefile-toolkit.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/Makefile-toolkit.am
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| toolkit_cflags =				\ | ||||
|     -I$(top_srcdir)/src				\ | ||||
|     -DPREFIX=\""$(prefix)"\"			\ | ||||
|     -DLIBDIR=\""$(libdir)"\"			\ | ||||
|     -DG_DISABLE_DEPRECATED			\ | ||||
|     -DG_LOG_DOMAIN=\"Shell\"			\ | ||||
|     $(TOOLKIT_CFLAGS) | ||||
|  | ||||
| # please, keep this sorted alphabetically | ||||
| toolkit_sources =				\ | ||||
| 	toolkit/shell-border-image.c		\ | ||||
| 	toolkit/shell-border-image.h		\ | ||||
| 	toolkit/shell-theme.c			\ | ||||
| 	toolkit/shell-theme.h			\ | ||||
| 	toolkit/shell-theme-context.c		\ | ||||
| 	toolkit/shell-theme-context.h		\ | ||||
| 	toolkit/shell-theme-node.c		\ | ||||
| 	toolkit/shell-theme-node.h		\ | ||||
| 	toolkit/shell-theme-private.h | ||||
|  | ||||
| non_gir_toolkit_sources =			\ | ||||
| 	toolkit/shell-theme-private.h | ||||
|  | ||||
| noinst_LTLIBRARIES += libshell-toolkit.la | ||||
|  | ||||
| libshell_toolkit_la_LIBADD = $(TOOLKIT_LIBS) | ||||
| libshell_toolkit_la_SOURCES = $(toolkit_sources) $(toolkit_built_sources) | ||||
| libshell_toolkit_la_CPPFLAGS = $(toolkit_cflags) | ||||
| libshell_toolkit_la_LDFLAGS = $(LDADD) | ||||
|  | ||||
| noinst_PROGRAMS += test-theme | ||||
|  | ||||
| test_theme_CPPFLAGS = $(toolkit_cflags) | ||||
| test_theme_LDADD = libshell-toolkit.la | ||||
|  | ||||
| test_theme_SOURCES = toolkit/test-theme.c | ||||
| @@ -4,6 +4,7 @@ CLEANFILES = | ||||
| EXTRA_DIST = | ||||
| libexec_PROGRAMS = | ||||
| noinst_LTLIBRARIES = | ||||
| noinst_PROGRAMS = | ||||
|  | ||||
| .AUTOPARALLEL: | ||||
|  | ||||
| @@ -24,6 +25,8 @@ EXTRA_DIST += gnome-shell.in | ||||
|  | ||||
| include Makefile-big.am | ||||
| include Makefile-gdmuser.am | ||||
| include Makefile-nbtk.am | ||||
| include Makefile-toolkit.am | ||||
| include Makefile-tray.am | ||||
|  | ||||
| gnome_shell_cflags =				\ | ||||
| @@ -96,7 +99,7 @@ libgnome_shell_la_SOURCES =			\ | ||||
| 	shell-wm.c				\ | ||||
| 	shell-wm.h | ||||
|  | ||||
| non_gir_sources =						\ | ||||
| non_gir_sources =				\ | ||||
| 	shell-embedded-window-private.h | ||||
|  | ||||
| shell_recorder_sources =        \ | ||||
| @@ -114,7 +117,7 @@ if BUILD_RECORDER | ||||
| libgnome_shell_la_SOURCES += $(shell_recorder_sources) | ||||
| non_gir_sources += $(shell_recorder_non_gir_sources) | ||||
|  | ||||
| noinst_PROGRAMS = test-recorder | ||||
| noinst_PROGRAMS += test-recorder | ||||
|  | ||||
| test_recorder_CPPFLAGS = $(TEST_SHELL_RECORDER_CFLAGS) | ||||
| test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS) | ||||
| @@ -125,7 +128,7 @@ test_recorder_SOURCES =     \ | ||||
| endif BUILD_RECORDER | ||||
|  | ||||
| libgnome_shell_la_gir_sources = \ | ||||
| 	$(filter-out $(non_gir_sources), $(libgnome_shell_la_SOURCES)) | ||||
| 	$(filter-out $(non_gir_sources) $(non_gir_toolkit_sources), $(libgnome_shell_la_SOURCES) $(toolkit_sources)) | ||||
|  | ||||
| shell-marshal.h: stamp-shell-marshal.h | ||||
| 	@true | ||||
| @@ -152,14 +155,16 @@ libgnome_shell_la_LIBADD =	\ | ||||
| 	$(MUTTER_PLUGIN_LIBS)	\ | ||||
|         $(LIBGNOMEUI_LIBS)      \ | ||||
| 	libbig-1.0.la		\ | ||||
| 	libnbtk-1.0.la       	\ | ||||
| 	libgdmuser-1.0.la	\ | ||||
| 	libshell-toolkit.la	\ | ||||
| 	libtray.la | ||||
| libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags) | ||||
|  | ||||
| typelibdir = $(pkglibdir) | ||||
| typelib_DATA = Shell-0.1.typelib Big-1.0.typelib | ||||
| typelib_DATA = Shell-0.1.typelib Big-1.0.typelib Nbtk-1.0.typelib | ||||
|  | ||||
| Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir libgnome-shell.la Makefile | ||||
| Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir Nbtk-1.0.gir libgnome-shell.la Makefile | ||||
| 	$(AM_V_GEN) $(G_IR_SCANNER)			\ | ||||
| 		--namespace=Shell			\ | ||||
| 		--nsversion=0.1				\ | ||||
| @@ -169,6 +174,7 @@ Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir libgnome-shell.la Makefile | ||||
| 		--libtool="$(LIBTOOL)"    \ | ||||
| 		--add-include-path=$(builddir)     \ | ||||
| 		--include=Big-1.0     \ | ||||
| 		--include=Nbtk-1.0     \ | ||||
| 		--program=mutter			\ | ||||
| 	        --program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \ | ||||
| 		$(addprefix $(srcdir)/,$(libgnome_shell_la_gir_sources)) \ | ||||
| @@ -179,14 +185,14 @@ CLEANFILES += Shell-0.1.gir | ||||
| # The dependency on libgnome-shell.la here is because g-ir-compiler opens it | ||||
| # (not the fake library, since we've already done the rewriting) | ||||
| Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir Big-1.0.gir | ||||
| 	$(AM_V_GEN) LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH}	\ | ||||
| 	$(AM_V_GEN) \ | ||||
| 		$(G_IR_COMPILER)						\ | ||||
| 			--includedir=.						\ | ||||
| 			--includedir=$(MUTTER_LIB_DIR)/mutter/			\ | ||||
| 		Shell-0.1.gir -o $@ | ||||
| CLEANFILES += Shell-0.1.typelib | ||||
|  | ||||
| Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la $(srcdir)/big-enum-types.h Makefile | ||||
| Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la Makefile | ||||
| 	$(AM_V_GEN) $(G_IR_SCANNER)			\ | ||||
| 		--namespace=Big				\ | ||||
| 		--nsversion=1.0				\ | ||||
| @@ -203,6 +209,54 @@ Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la $(srcdir) | ||||
| CLEANFILES += Big-1.0.gir | ||||
|  | ||||
| Big-1.0.typelib: libbig-1.0.la Big-1.0.gir | ||||
| 	$(AM_V_GEN) LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH} \ | ||||
| 		$(G_IR_COMPILER) Big-1.0.gir -o $@ | ||||
| 	$(AM_V_GEN) $(G_IR_COMPILER) Big-1.0.gir -o $@ | ||||
| CLEANFILES += Big-1.0.typelib | ||||
|  | ||||
| toolkit_gir_sources = \ | ||||
| 	$(filter-out $(non_gir_toolkit_sources), $(toolkit_sources)) | ||||
|  | ||||
| # Since the Shell namepace includes both the code in toolkit/ that our fork of | ||||
| # NBTK depends upon and the code in this directory that depends on NBTK, We have a | ||||
| # circular dependency when generating the girs and typelibs. We work around this | ||||
| # by generating a Toolkit gir, using it to build the Nbtk gir then sed'ing the | ||||
| # reference out of the generated gir. | ||||
| Toolkit-0.1.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libshell-toolkit.la Makefile | ||||
| 	$(AM_V_GEN) $(G_IR_SCANNER)						\ | ||||
| 	        --namespace=Shell						\ | ||||
| 		--nsversion=0.1							\ | ||||
| 	        --include=Clutter-1.0						\ | ||||
| 	        --libtool="$(LIBTOOL)"						\ | ||||
| 	        --program=mutter						\ | ||||
| 		--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la	\ | ||||
| 	        $(addprefix $(srcdir)/,$(toolkit_gir_sources))			\ | ||||
| 	        $(TOOLKIT_CFLAGS)						\ | ||||
| 	        -o $@ | ||||
| CLEANFILES += Toolkit-1.0.gir | ||||
|  | ||||
| Nbtk-1.0.gir: $(mutter) $(G_IR_SCANNER) Toolkit-0.1.gir libgnome-shell.la libnbtk-1.0.la Makefile | ||||
| 	$(AM_V_GEN) $(G_IR_SCANNER)						\ | ||||
| 	        --namespace=Nbtk						\ | ||||
| 	        --nsversion=1.0							\ | ||||
| 	        --include=Clutter-1.0						\ | ||||
| 	        --include=Gtk-2.0						\ | ||||
| 		--add-include-path=$(builddir)     				\ | ||||
| 		--include=Toolkit-0.1						\ | ||||
| 	        --libtool="$(LIBTOOL)"						\ | ||||
| 	        --program=mutter						\ | ||||
| 		--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la	\ | ||||
| 	        -DNBTK_COMPILATION						\ | ||||
| 	        $(addprefix $(srcdir)/,$(nbtk_source_h))			\ | ||||
| 	        $(addprefix $(srcdir)/,$(nbtk_source_c))			\ | ||||
| 	        $(srcdir)/nbtk-enum-types.h					\ | ||||
| 	        $(NBTK_CFLAGS)							\ | ||||
| 	        -o $@.tmp &&							\ | ||||
| 	sed -e '/"Toolkit"/d' < $@.tmp > $@ | ||||
| CLEANFILES += Nbtk-1.0.gir | ||||
|  | ||||
| Nbtk-1.0.typelib: Nbtk-1.0.gir | ||||
| 	$(AM_V_GEN) $(G_IR_COMPILER)						\ | ||||
| 		--includedir=.							\ | ||||
| 		--includedir=$(MUTTER_LIB_DIR)/mutter/				\ | ||||
| 		$< -o $@ | ||||
|  | ||||
| CLEANFILES += Nbtk-1.0.typelib | ||||
|   | ||||
| @@ -268,6 +268,52 @@ corner_get(guint         radius, | ||||
|     return corner; | ||||
| } | ||||
|  | ||||
| /* To match the CSS specification, we want the border to look like it was | ||||
|  * drawn over the background. But actually drawing the border over the | ||||
|  * background will produce slightly bad antialiasing at the edges, so | ||||
|  * compute the effective border color instead. | ||||
|  */ | ||||
| #define NORM(x) (t = (x) + 127, (t + (t >> 8)) >> 8) | ||||
| #define MULT(c,a) NORM(c*a) | ||||
|  | ||||
| static void | ||||
| premultiply (ClutterColor *color) | ||||
| { | ||||
|     guint t; | ||||
|     color->red = MULT (color->red, color->alpha); | ||||
|     color->green = MULT (color->green, color->alpha); | ||||
|     color->blue = MULT (color->blue, color->alpha); | ||||
| } | ||||
|  | ||||
| static void | ||||
| unpremultiply (ClutterColor *color) | ||||
| { | ||||
|     if (color->alpha != 0) { | ||||
|         color->red = (color->red * 255 + 127) / color->alpha; | ||||
|         color->green = (color->green * 255 + 127) / color->alpha; | ||||
|         color->blue = (color->blue * 255 + 127) / color->alpha; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| over (const ClutterColor *source, | ||||
|       const ClutterColor *destination, | ||||
|       ClutterColor       *result) | ||||
| { | ||||
|     guint t; | ||||
|     ClutterColor src = *source; | ||||
|     ClutterColor dst = *destination; | ||||
|     premultiply (&src); | ||||
|     premultiply (&dst); | ||||
|  | ||||
|     result->alpha = src.alpha + NORM ((255 - src.alpha) * dst.alpha); | ||||
|     result->red   = src.red +   NORM ((255 - src.alpha) * dst.red); | ||||
|     result->green = src.green + NORM ((255 - src.alpha) * dst.green); | ||||
|     result->blue  = src.blue +  NORM ((255 - src.alpha) * dst.blue); | ||||
|  | ||||
|     unpremultiply (result); | ||||
| } | ||||
|  | ||||
| static void | ||||
| big_rectangle_update_corners(BigRectangle *rectangle) | ||||
| { | ||||
| @@ -278,6 +324,7 @@ big_rectangle_update_corners(BigRectangle *rectangle) | ||||
|     if (rectangle->radius != 0) { | ||||
|         ClutterColor *color; | ||||
|         ClutterColor *border_color; | ||||
|         ClutterColor effective_border; | ||||
|         guint border_width; | ||||
|  | ||||
|         g_object_get(rectangle, | ||||
| @@ -286,10 +333,12 @@ big_rectangle_update_corners(BigRectangle *rectangle) | ||||
|                      "color", &color, | ||||
|                      NULL); | ||||
|  | ||||
|         over (border_color, color, &effective_border); | ||||
|  | ||||
|         corner = corner_get(rectangle->radius, | ||||
|                             color, | ||||
|                             border_width, | ||||
|                             border_color); | ||||
|                             &effective_border); | ||||
|  | ||||
|         clutter_color_free(border_color); | ||||
|         clutter_color_free(color); | ||||
| @@ -329,12 +378,10 @@ big_rectangle_paint(ClutterActor *actor) | ||||
|  | ||||
|     rectangle = BIG_RECTANGLE(actor); | ||||
|  | ||||
|     if (rectangle->radius == 0) { | ||||
|         /* In that case we are no different than our parent class, | ||||
|          * so don't bother */ | ||||
|         CLUTTER_ACTOR_CLASS(big_rectangle_parent_class)->paint(actor); | ||||
|         return; | ||||
|     } | ||||
|     /* We can't chain up, even when we the radius is 0, because of the different | ||||
|      * interpretation of the border/background relationship here than for | ||||
|      * ClutterRectangle. | ||||
|      */ | ||||
|  | ||||
|     if (rectangle->corners_dirty) | ||||
|         big_rectangle_update_corners(rectangle); | ||||
| @@ -345,6 +392,9 @@ big_rectangle_paint(ClutterActor *actor) | ||||
|                  "color", &color, | ||||
|                  NULL); | ||||
|  | ||||
|     if (border_color->alpha == 0 && color->alpha == 0) | ||||
|         goto out; | ||||
|  | ||||
|     actor_opacity = clutter_actor_get_paint_opacity (actor); | ||||
|  | ||||
|     clutter_actor_get_allocation_box(actor, &box); | ||||
| @@ -358,6 +408,11 @@ big_rectangle_paint(ClutterActor *actor) | ||||
|  | ||||
|     radius = rectangle->radius; | ||||
|  | ||||
|     /* Optimization; if the border is transparent, it just looks like part of | ||||
|      * the background */ | ||||
|     if (radius == 0 && border_color->alpha == 0) | ||||
|         border_width = 0; | ||||
|  | ||||
|     max = MAX(border_width, radius); | ||||
|  | ||||
|     if (radius != 0) { | ||||
| @@ -393,33 +448,54 @@ big_rectangle_paint(ClutterActor *actor) | ||||
|     } | ||||
|  | ||||
|     if (border_width != 0) { | ||||
|         ClutterColor effective_border; | ||||
|         over (border_color, color, &effective_border); | ||||
|  | ||||
|         if (!rectangle->border_material) | ||||
|             rectangle->border_material = cogl_material_new (); | ||||
|  | ||||
|         cogl_color_set_from_4ub(&tmp_color, | ||||
|                                 border_color->red, | ||||
|                                 border_color->green, | ||||
|                                 border_color->blue, | ||||
|                                 actor_opacity * border_color->alpha / 255); | ||||
|                                 effective_border.red, | ||||
|                                 effective_border.green, | ||||
|                                 effective_border.blue, | ||||
|                                 actor_opacity * effective_border.alpha / 255); | ||||
|         cogl_color_premultiply (&tmp_color); | ||||
|         cogl_material_set_color(rectangle->border_material, &tmp_color); | ||||
|         cogl_set_source(rectangle->border_material); | ||||
|  | ||||
|         /* NORTH */ | ||||
|         cogl_rectangle(max, 0, | ||||
|                        width - max, border_width); | ||||
|         if (radius > 0) { /* skip corners */ | ||||
|             /* NORTH */ | ||||
|             cogl_rectangle(max, 0, | ||||
|                            width - max, border_width); | ||||
|  | ||||
|         /* EAST */ | ||||
|         cogl_rectangle(width - border_width, max, | ||||
|                        width, height - max); | ||||
|             /* EAST */ | ||||
|             cogl_rectangle(width - border_width, max, | ||||
|                            width, height - max); | ||||
|  | ||||
|         /* SOUTH */ | ||||
|         cogl_rectangle(max, height - border_width, | ||||
|                        width - max, height); | ||||
|             /* SOUTH */ | ||||
|             cogl_rectangle(max, height - border_width, | ||||
|                            width - max, height); | ||||
|  | ||||
|         /* WEST */ | ||||
|         cogl_rectangle(0, max, | ||||
|                        border_width, height - max); | ||||
|             /* WEST */ | ||||
|             cogl_rectangle(0, max, | ||||
|                            border_width, height - max); | ||||
|         } else { /* include corners */ | ||||
|             /* NORTH */ | ||||
|             cogl_rectangle(0, 0, | ||||
|                            width, border_width); | ||||
|  | ||||
|             /* EAST */ | ||||
|             cogl_rectangle(width - border_width, border_width, | ||||
|                            width, height - border_width); | ||||
|  | ||||
|             /* SOUTH */ | ||||
|             cogl_rectangle(0, height - border_width, | ||||
|                            width, height); | ||||
|  | ||||
|             /* WEST */ | ||||
|             cogl_rectangle(0, border_width, | ||||
|                            border_width, height - border_width); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!rectangle->background_material) | ||||
| @@ -455,6 +531,7 @@ big_rectangle_paint(ClutterActor *actor) | ||||
|     cogl_rectangle(border_width, max, | ||||
|                    width - border_width, height - max); | ||||
|  | ||||
| out: | ||||
|     clutter_color_free(border_color); | ||||
|     clutter_color_free(color); | ||||
| } | ||||
|   | ||||
| @@ -1,64 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #include <mutter-plugin.h> | ||||
|  | ||||
| ClutterActor * | ||||
| mutter_plugin_get_overlay_group (MutterPlugin *plugin) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| ClutterActor * | ||||
| mutter_plugin_get_stage (MutterPlugin *plugin) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| GList * | ||||
| mutter_plugin_get_windows (MutterPlugin *plugin) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| void | ||||
| mutter_plugin_query_screen_size (MutterPlugin *plugin, | ||||
|                                  int          *width, | ||||
|                                  int          *height) | ||||
| { | ||||
| } | ||||
|  | ||||
| void | ||||
| mutter_plugin_set_stage_input_area (MutterPlugin *plugin, | ||||
|                                     gint x, gint y, gint width, gint height) | ||||
| { | ||||
| } | ||||
|  | ||||
| MetaScreen * | ||||
| mutter_plugin_get_screen (MutterPlugin *plugin) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| ClutterActor * | ||||
| mutter_plugin_get_window_group (MutterPlugin *plugin) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| Display * | ||||
| meta_display_get_xdisplay (MetaDisplay *display) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| MetaDisplay * | ||||
| meta_screen_get_display (MetaScreen *display) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| Window | ||||
| meta_screen_get_xroot (MetaScreen *display) | ||||
| { | ||||
|   return None; | ||||
| } | ||||
							
								
								
									
										768
									
								
								src/nbtk/nbtk-adjustment.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										768
									
								
								src/nbtk/nbtk-adjustment.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,768 @@ | ||||
| /* | ||||
|  * nbtk-adjustment.c: Adjustment object | ||||
|  * | ||||
|  * Copyright (C) 2008 OpenedHand | ||||
|  * Copyright (c) 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Chris Lord <chris@openedhand.com>, inspired by GtkAdjustment | ||||
|  * Port to Nbtk by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "nbtk-adjustment.h" | ||||
| #include "nbtk-marshal.h" | ||||
| #include "nbtk-private.h" | ||||
|  | ||||
| G_DEFINE_TYPE (NbtkAdjustment, nbtk_adjustment, G_TYPE_OBJECT) | ||||
|  | ||||
| #define ADJUSTMENT_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_ADJUSTMENT, NbtkAdjustmentPrivate)) | ||||
|  | ||||
| struct _NbtkAdjustmentPrivate | ||||
| { | ||||
|   /* Do not sanity-check values while constructing, | ||||
|    * not all properties may be set yet. */ | ||||
|   gboolean is_constructing : 1; | ||||
|  | ||||
|   gdouble lower; | ||||
|   gdouble upper; | ||||
|   gdouble value; | ||||
|   gdouble step_increment; | ||||
|   gdouble page_increment; | ||||
|   gdouble page_size; | ||||
|  | ||||
|   /* For interpolation */ | ||||
|   ClutterTimeline *interpolation; | ||||
|   gdouble old_position; | ||||
|   gdouble new_position; | ||||
|  | ||||
|   /* For elasticity */ | ||||
|   gboolean      elastic; | ||||
|   guint         bounce_source; | ||||
|   ClutterAlpha *bounce_alpha; | ||||
| }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_LOWER, | ||||
|   PROP_UPPER, | ||||
|   PROP_VALUE, | ||||
|   PROP_STEP_INC, | ||||
|   PROP_PAGE_INC, | ||||
|   PROP_PAGE_SIZE, | ||||
|  | ||||
|   PROP_ELASTIC, | ||||
| }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   CHANGED, | ||||
|  | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL] = { 0, }; | ||||
|  | ||||
| static gboolean nbtk_adjustment_set_lower          (NbtkAdjustment *adjustment, | ||||
|                                                     gdouble         lower); | ||||
| static gboolean nbtk_adjustment_set_upper          (NbtkAdjustment *adjustment, | ||||
|                                                     gdouble         upper); | ||||
| static gboolean nbtk_adjustment_set_step_increment (NbtkAdjustment *adjustment, | ||||
|                                                     gdouble         step); | ||||
| static gboolean nbtk_adjustment_set_page_increment (NbtkAdjustment *adjustment, | ||||
|                                                     gdouble         page); | ||||
| static gboolean nbtk_adjustment_set_page_size      (NbtkAdjustment *adjustment, | ||||
|                                                     gdouble         size); | ||||
|  | ||||
| static void | ||||
| nbtk_adjustment_constructed (GObject *object) | ||||
| { | ||||
|   GObjectClass *g_class; | ||||
|   NbtkAdjustment *self = NBTK_ADJUSTMENT (object); | ||||
|  | ||||
|   g_class = G_OBJECT_CLASS (nbtk_adjustment_parent_class); | ||||
|   /* The docs say we're suppose to chain up, but would crash without | ||||
|    * some extra care. */ | ||||
|   if (g_class && g_class->constructed && | ||||
|       g_class->constructed != nbtk_adjustment_constructed) | ||||
|     { | ||||
|       g_class->constructed (object); | ||||
|     } | ||||
|  | ||||
|   NBTK_ADJUSTMENT (self)->priv->is_constructing = FALSE; | ||||
|   nbtk_adjustment_clamp_page (self, self->priv->lower, self->priv->upper); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_adjustment_get_property (GObject    *gobject, | ||||
|                               guint       prop_id, | ||||
|                               GValue     *value, | ||||
|                               GParamSpec *pspec) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv = NBTK_ADJUSTMENT (gobject)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_LOWER: | ||||
|       g_value_set_double (value, priv->lower); | ||||
|       break; | ||||
|  | ||||
|     case PROP_UPPER: | ||||
|       g_value_set_double (value, priv->upper); | ||||
|       break; | ||||
|  | ||||
|     case PROP_VALUE: | ||||
|       g_value_set_double (value, priv->value); | ||||
|       break; | ||||
|  | ||||
|     case PROP_STEP_INC: | ||||
|       g_value_set_double (value, priv->step_increment); | ||||
|       break; | ||||
|  | ||||
|     case PROP_PAGE_INC: | ||||
|       g_value_set_double (value, priv->page_increment); | ||||
|       break; | ||||
|  | ||||
|     case PROP_PAGE_SIZE: | ||||
|       g_value_set_double (value, priv->page_size); | ||||
|       break; | ||||
|  | ||||
|     case PROP_ELASTIC: | ||||
|       g_value_set_boolean (value, priv->elastic); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_adjustment_set_property (GObject      *gobject, | ||||
|                               guint         prop_id, | ||||
|                               const GValue *value, | ||||
|                               GParamSpec   *pspec) | ||||
| { | ||||
|   NbtkAdjustment *adj = NBTK_ADJUSTMENT (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_LOWER: | ||||
|       nbtk_adjustment_set_lower (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_UPPER: | ||||
|       nbtk_adjustment_set_upper (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_VALUE: | ||||
|       nbtk_adjustment_set_value (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_STEP_INC: | ||||
|       nbtk_adjustment_set_step_increment (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_PAGE_INC: | ||||
|       nbtk_adjustment_set_page_increment (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_PAGE_SIZE: | ||||
|       nbtk_adjustment_set_page_size (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_ELASTIC: | ||||
|       nbtk_adjustment_set_elastic (adj, g_value_get_boolean (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| stop_interpolation (NbtkAdjustment *adjustment) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv = adjustment->priv; | ||||
|  | ||||
|   if (priv->interpolation) | ||||
|     { | ||||
|       clutter_timeline_stop (priv->interpolation); | ||||
|       g_object_unref (priv->interpolation); | ||||
|       priv->interpolation = NULL; | ||||
|  | ||||
|       if (priv->bounce_alpha) | ||||
|         { | ||||
|           g_object_unref (priv->bounce_alpha); | ||||
|           priv->bounce_alpha = NULL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   if (priv->bounce_source) | ||||
|     { | ||||
|       g_source_remove (priv->bounce_source); | ||||
|       priv->bounce_source = 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_adjustment_dispose (GObject *object) | ||||
| { | ||||
|   stop_interpolation (NBTK_ADJUSTMENT (object)); | ||||
|  | ||||
|   G_OBJECT_CLASS (nbtk_adjustment_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_adjustment_class_init (NbtkAdjustmentClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (NbtkAdjustmentPrivate)); | ||||
|  | ||||
|   object_class->constructed = nbtk_adjustment_constructed; | ||||
|   object_class->get_property = nbtk_adjustment_get_property; | ||||
|   object_class->set_property = nbtk_adjustment_set_property; | ||||
|   object_class->dispose = nbtk_adjustment_dispose; | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_LOWER, | ||||
|                                    g_param_spec_double ("lower", | ||||
|                                                         "Lower", | ||||
|                                                         "Lower bound", | ||||
|                                                         -G_MAXDOUBLE, | ||||
|                                                         G_MAXDOUBLE, | ||||
|                                                         0.0, | ||||
|                                                         NBTK_PARAM_READWRITE | | ||||
|                                                         G_PARAM_CONSTRUCT)); | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_UPPER, | ||||
|                                    g_param_spec_double ("upper", | ||||
|                                                         "Upper", | ||||
|                                                         "Upper bound", | ||||
|                                                         -G_MAXDOUBLE, | ||||
|                                                         G_MAXDOUBLE, | ||||
|                                                         0.0, | ||||
|                                                         NBTK_PARAM_READWRITE | | ||||
|                                                         G_PARAM_CONSTRUCT)); | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_VALUE, | ||||
|                                    g_param_spec_double ("value", | ||||
|                                                         "Value", | ||||
|                                                         "Current value", | ||||
|                                                         -G_MAXDOUBLE, | ||||
|                                                         G_MAXDOUBLE, | ||||
|                                                         0.0, | ||||
|                                                         NBTK_PARAM_READWRITE | | ||||
|                                                         G_PARAM_CONSTRUCT)); | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_STEP_INC, | ||||
|                                    g_param_spec_double ("step-increment", | ||||
|                                                         "Step Increment", | ||||
|                                                         "Step increment", | ||||
|                                                         0.0, | ||||
|                                                         G_MAXDOUBLE, | ||||
|                                                         0.0, | ||||
|                                                         NBTK_PARAM_READWRITE | | ||||
|                                                         G_PARAM_CONSTRUCT)); | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_PAGE_INC, | ||||
|                                    g_param_spec_double ("page-increment", | ||||
|                                                         "Page Increment", | ||||
|                                                         "Page increment", | ||||
|                                                         0.0, | ||||
|                                                         G_MAXDOUBLE, | ||||
|                                                         0.0, | ||||
|                                                         NBTK_PARAM_READWRITE | | ||||
|                                                         G_PARAM_CONSTRUCT)); | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_PAGE_SIZE, | ||||
|                                    g_param_spec_double ("page-size", | ||||
|                                                         "Page Size", | ||||
|                                                         "Page size", | ||||
|                                                         0.0, | ||||
|                                                         G_MAXDOUBLE, | ||||
|                                                         0.0, | ||||
|                                                         NBTK_PARAM_READWRITE | | ||||
|                                                         G_PARAM_CONSTRUCT)); | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_ELASTIC, | ||||
|                                    g_param_spec_boolean ("elastic", | ||||
|                                                          "Elastic", | ||||
|                                                          "Make interpolation " | ||||
|                                                          "behave in an " | ||||
|                                                          "'elastic' way and " | ||||
|                                                          "stop clamping value.", | ||||
|                                                          FALSE, | ||||
|                                                         NBTK_PARAM_READWRITE | | ||||
|                                                         G_PARAM_CONSTRUCT)); | ||||
|  | ||||
|   /** | ||||
|    * NbtkAdjustment::changed: | ||||
|    * | ||||
|    * Emitted when any of the adjustment values have changed | ||||
|    */ | ||||
|   signals[CHANGED] = | ||||
|     g_signal_new ("changed", | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   G_STRUCT_OFFSET (NbtkAdjustmentClass, changed), | ||||
|                   NULL, NULL, | ||||
|                   _nbtk_marshal_VOID__VOID, | ||||
|                   G_TYPE_NONE, 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_adjustment_init (NbtkAdjustment *self) | ||||
| { | ||||
|   self->priv = ADJUSTMENT_PRIVATE (self); | ||||
|  | ||||
|   self->priv->is_constructing = TRUE; | ||||
| } | ||||
|  | ||||
| NbtkAdjustment * | ||||
| nbtk_adjustment_new (gdouble value, | ||||
|                      gdouble lower, | ||||
|                      gdouble upper, | ||||
|                      gdouble step_increment, | ||||
|                      gdouble page_increment, | ||||
|                      gdouble page_size) | ||||
| { | ||||
|   return g_object_new (NBTK_TYPE_ADJUSTMENT, | ||||
|                        "value", value, | ||||
|                        "lower", lower, | ||||
|                        "upper", upper, | ||||
|                        "step-increment", step_increment, | ||||
|                        "page-increment", page_increment, | ||||
|                        "page-size", page_size, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| gdouble | ||||
| nbtk_adjustment_get_value (NbtkAdjustment *adjustment) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv; | ||||
|  | ||||
|   g_return_val_if_fail (NBTK_IS_ADJUSTMENT (adjustment), 0); | ||||
|  | ||||
|   priv = adjustment->priv; | ||||
|  | ||||
|   if (priv->interpolation) | ||||
|     { | ||||
|       return MAX (priv->lower, | ||||
|                   MIN (priv->upper - priv->page_size, | ||||
|                        priv->new_position)); | ||||
|     } | ||||
|   else | ||||
|     return priv->value; | ||||
| } | ||||
|  | ||||
| void | ||||
| nbtk_adjustment_set_value (NbtkAdjustment *adjustment, | ||||
|                            gdouble         value) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment)); | ||||
|  | ||||
|   priv = adjustment->priv; | ||||
|  | ||||
|   stop_interpolation (adjustment); | ||||
|  | ||||
|   /* Defer clamp until after construction. */ | ||||
|   if (!priv->is_constructing) | ||||
|     { | ||||
|       if (!priv->elastic) | ||||
|         value = CLAMP (value, | ||||
|                        priv->lower, | ||||
|                        MAX (priv->lower, priv->upper - priv->page_size)); | ||||
|     } | ||||
|  | ||||
|   if (priv->value != value) | ||||
|     { | ||||
|       priv->value = value; | ||||
|  | ||||
|       g_object_notify (G_OBJECT (adjustment), "value"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| nbtk_adjustment_clamp_page (NbtkAdjustment *adjustment, | ||||
|                             gdouble         lower, | ||||
|                             gdouble         upper) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv; | ||||
|   gboolean changed; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment)); | ||||
|  | ||||
|   priv = adjustment->priv; | ||||
|  | ||||
|   stop_interpolation (adjustment); | ||||
|  | ||||
|   lower = CLAMP (lower, priv->lower, priv->upper - priv->page_size); | ||||
|   upper = CLAMP (upper, priv->lower + priv->page_size, priv->upper); | ||||
|  | ||||
|   changed = FALSE; | ||||
|  | ||||
|   if (priv->value + priv->page_size > upper) | ||||
|     { | ||||
|       priv->value = upper - priv->page_size; | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (priv->value < lower) | ||||
|     { | ||||
|       priv->value = lower; | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (changed) | ||||
|     g_object_notify (G_OBJECT (adjustment), "value"); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| nbtk_adjustment_set_lower (NbtkAdjustment *adjustment, | ||||
|                            gdouble         lower) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv = adjustment->priv; | ||||
|  | ||||
|   if (priv->lower != lower) | ||||
|     { | ||||
|       priv->lower = lower; | ||||
|  | ||||
|       g_signal_emit (adjustment, signals[CHANGED], 0); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (adjustment), "lower"); | ||||
|  | ||||
|       /* Defer clamp until after construction. */ | ||||
|       if (!priv->is_constructing) | ||||
|         nbtk_adjustment_clamp_page (adjustment, priv->lower, priv->upper); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| nbtk_adjustment_set_upper (NbtkAdjustment *adjustment, | ||||
|                            gdouble         upper) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv = adjustment->priv; | ||||
|  | ||||
|   if (priv->upper != upper) | ||||
|     { | ||||
|       priv->upper = upper; | ||||
|  | ||||
|       g_signal_emit (adjustment, signals[CHANGED], 0); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (adjustment), "upper"); | ||||
|  | ||||
|       /* Defer clamp until after construction. */ | ||||
|       if (!priv->is_constructing) | ||||
|         nbtk_adjustment_clamp_page (adjustment, priv->lower, priv->upper); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| nbtk_adjustment_set_step_increment (NbtkAdjustment *adjustment, | ||||
|                                     gdouble         step) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv = adjustment->priv; | ||||
|  | ||||
|   if (priv->step_increment != step) | ||||
|     { | ||||
|       priv->step_increment = step; | ||||
|  | ||||
|       g_signal_emit (adjustment, signals[CHANGED], 0); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (adjustment), "step-increment"); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| nbtk_adjustment_set_page_increment (NbtkAdjustment *adjustment, | ||||
|                                     gdouble         page) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv = adjustment->priv; | ||||
|  | ||||
|   if (priv->page_increment != page) | ||||
|     { | ||||
|       priv->page_increment = page; | ||||
|  | ||||
|       g_signal_emit (adjustment, signals[CHANGED], 0); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (adjustment), "page-increment"); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| nbtk_adjustment_set_page_size (NbtkAdjustment *adjustment, | ||||
|                                gdouble         size) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv = adjustment->priv; | ||||
|  | ||||
|   if (priv->page_size != size) | ||||
|     { | ||||
|       priv->page_size = size; | ||||
|  | ||||
|       g_signal_emit (adjustment, signals[CHANGED], 0); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (adjustment), "page_size"); | ||||
|  | ||||
|       /* Well explicitely clamp after construction. */ | ||||
|       if (!priv->is_constructing) | ||||
|         nbtk_adjustment_clamp_page (adjustment, priv->lower, priv->upper); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| void | ||||
| nbtk_adjustment_set_values (NbtkAdjustment *adjustment, | ||||
|                             gdouble         value, | ||||
|                             gdouble         lower, | ||||
|                             gdouble         upper, | ||||
|                             gdouble         step_increment, | ||||
|                             gdouble         page_increment, | ||||
|                             gdouble         page_size) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv; | ||||
|   gboolean emit_changed = FALSE; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment)); | ||||
|   g_return_if_fail (page_size >= 0 && page_size <= G_MAXDOUBLE); | ||||
|   g_return_if_fail (step_increment >= 0 && step_increment <= G_MAXDOUBLE); | ||||
|   g_return_if_fail (page_increment >= 0 && page_increment <= G_MAXDOUBLE); | ||||
|  | ||||
|   priv = adjustment->priv; | ||||
|  | ||||
|   stop_interpolation (adjustment); | ||||
|  | ||||
|   emit_changed = FALSE; | ||||
|  | ||||
|   g_object_freeze_notify (G_OBJECT (adjustment)); | ||||
|  | ||||
|   emit_changed |= nbtk_adjustment_set_lower (adjustment, lower); | ||||
|   emit_changed |= nbtk_adjustment_set_upper (adjustment, upper); | ||||
|   emit_changed |= nbtk_adjustment_set_step_increment (adjustment, step_increment); | ||||
|   emit_changed |= nbtk_adjustment_set_page_increment (adjustment, page_increment); | ||||
|   emit_changed |= nbtk_adjustment_set_page_size (adjustment, page_size); | ||||
|  | ||||
|   if (value != priv->value) | ||||
|     { | ||||
|       nbtk_adjustment_set_value (adjustment, value); | ||||
|       emit_changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (emit_changed) | ||||
|     g_signal_emit (G_OBJECT (adjustment), signals[CHANGED], 0); | ||||
|  | ||||
|   g_object_thaw_notify (G_OBJECT (adjustment)); | ||||
| } | ||||
|  | ||||
| void | ||||
| nbtk_adjustment_get_values (NbtkAdjustment *adjustment, | ||||
|                             gdouble        *value, | ||||
|                             gdouble        *lower, | ||||
|                             gdouble        *upper, | ||||
|                             gdouble        *step_increment, | ||||
|                             gdouble        *page_increment, | ||||
|                             gdouble        *page_size) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment)); | ||||
|  | ||||
|   priv = adjustment->priv; | ||||
|  | ||||
|   if (lower) | ||||
|     *lower = priv->lower; | ||||
|  | ||||
|   if (upper) | ||||
|     *upper = priv->upper; | ||||
|  | ||||
|   if (value) | ||||
|     *value = nbtk_adjustment_get_value (adjustment); | ||||
|  | ||||
|   if (step_increment) | ||||
|     *step_increment = priv->step_increment; | ||||
|  | ||||
|   if (page_increment) | ||||
|     *page_increment = priv->page_increment; | ||||
|  | ||||
|   if (page_size) | ||||
|     *page_size = priv->page_size; | ||||
| } | ||||
|  | ||||
| static void | ||||
| interpolation_new_frame_cb (ClutterTimeline *timeline, | ||||
|                             guint            msecs, | ||||
|                             NbtkAdjustment  *adjustment) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv = adjustment->priv; | ||||
|  | ||||
|   priv->interpolation = NULL; | ||||
|  | ||||
|   if (priv->elastic) | ||||
|     { | ||||
|       gdouble progress = clutter_alpha_get_alpha (priv->bounce_alpha) / 1.0; | ||||
|       gdouble dx = priv->old_position | ||||
|                  + (priv->new_position - priv->old_position) | ||||
|                  * progress; | ||||
|  | ||||
|       nbtk_adjustment_set_value (adjustment, dx); | ||||
|     } | ||||
|   else | ||||
|     nbtk_adjustment_set_value (adjustment, | ||||
|                                priv->old_position + | ||||
|                                (priv->new_position - priv->old_position) * | ||||
|                                clutter_timeline_get_progress (timeline)); | ||||
|  | ||||
|   priv->interpolation = timeline; | ||||
| } | ||||
|  | ||||
| static void | ||||
| interpolation_completed_cb (ClutterTimeline *timeline, | ||||
|                             NbtkAdjustment  *adjustment) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv = adjustment->priv; | ||||
|  | ||||
|   stop_interpolation (adjustment); | ||||
|   nbtk_adjustment_set_value (adjustment, priv->new_position); | ||||
| } | ||||
|  | ||||
| /* Note, there's super-optimal code that does a similar thing in | ||||
|  * clutter-alpha.c | ||||
|  * | ||||
|  * Tried this instead of CLUTTER_ALPHA_SINE_INC, but I think SINE_INC looks | ||||
|  * better. Leaving code here in case this is revisited. | ||||
|  */ | ||||
| /* | ||||
| static guint32 | ||||
| bounce_alpha_func (ClutterAlpha *alpha, | ||||
|                    gpointer      user_data) | ||||
| { | ||||
|   ClutterFixed progress, angle; | ||||
|   ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha); | ||||
|  | ||||
|   progress = clutter_timeline_get_progressx (timeline); | ||||
|   angle = clutter_qmulx (CFX_PI_2 + CFX_PI_4/2, progress); | ||||
|  | ||||
|   return clutter_sinx (angle) + | ||||
|     (CFX_ONE - clutter_sinx (CFX_PI_2 + CFX_PI_4/2)); | ||||
| } | ||||
| */ | ||||
|  | ||||
| void | ||||
| nbtk_adjustment_interpolate (NbtkAdjustment *adjustment, | ||||
|                              gdouble         value, | ||||
|                              guint           duration) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv = adjustment->priv; | ||||
|  | ||||
|   stop_interpolation (adjustment); | ||||
|  | ||||
|   if (duration <= 1) | ||||
|     { | ||||
|       nbtk_adjustment_set_value (adjustment, value); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   priv->old_position = priv->value; | ||||
|   priv->new_position = value; | ||||
|  | ||||
|   priv->interpolation = clutter_timeline_new (duration); | ||||
|  | ||||
|   if (priv->elastic) | ||||
|     priv->bounce_alpha = clutter_alpha_new_full (priv->interpolation, | ||||
|                                                  CLUTTER_LINEAR); | ||||
|  | ||||
|   g_signal_connect (priv->interpolation, | ||||
|                     "new-frame", | ||||
|                     G_CALLBACK (interpolation_new_frame_cb), | ||||
|                     adjustment); | ||||
|   g_signal_connect (priv->interpolation, | ||||
|                     "completed", | ||||
|                     G_CALLBACK (interpolation_completed_cb), | ||||
|                     adjustment); | ||||
|  | ||||
|   clutter_timeline_start (priv->interpolation); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| nbtk_adjustment_get_elastic (NbtkAdjustment *adjustment) | ||||
| { | ||||
|   return adjustment->priv->elastic; | ||||
| } | ||||
|  | ||||
| void | ||||
| nbtk_adjustment_set_elastic (NbtkAdjustment *adjustment, | ||||
|                              gboolean        elastic) | ||||
| { | ||||
|   adjustment->priv->elastic = elastic; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| nbtk_adjustment_clamp (NbtkAdjustment *adjustment, | ||||
|                        gboolean        interpolate, | ||||
|                        guint           duration) | ||||
| { | ||||
|   NbtkAdjustmentPrivate *priv = adjustment->priv; | ||||
|   gdouble dest = priv->value; | ||||
|  | ||||
|   if (priv->value < priv->lower) | ||||
|     dest = priv->lower; | ||||
|  | ||||
|   if (priv->value > priv->upper - priv->page_size) | ||||
|     dest = priv->upper - priv->page_size; | ||||
|  | ||||
|   if (dest != priv->value) | ||||
|     { | ||||
|       if (interpolate) | ||||
|         nbtk_adjustment_interpolate (adjustment, dest, duration); | ||||
|       else | ||||
|         nbtk_adjustment_set_value (adjustment, dest); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
							
								
								
									
										121
									
								
								src/nbtk/nbtk-adjustment.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								src/nbtk/nbtk-adjustment.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | ||||
| /* | ||||
|  * nbtk-adjustment.h: Adjustment object | ||||
|  * | ||||
|  * Copyright 2008 OpenedHand | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Chris Lord <chris@openedhand.com>, inspired by GtkAdjustment | ||||
|  * Port to Nbtk by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_ADJUSTMENT_H__ | ||||
| #define __NBTK_ADJUSTMENT_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_ADJUSTMENT            (nbtk_adjustment_get_type()) | ||||
| #define NBTK_ADJUSTMENT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_ADJUSTMENT, NbtkAdjustment)) | ||||
| #define NBTK_IS_ADJUSTMENT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_ADJUSTMENT)) | ||||
| #define NBTK_ADJUSTMENT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_ADJUSTMENT, NbtkAdjustmentClass)) | ||||
| #define NBTK_IS_ADJUSTMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_ADJUSTMENT)) | ||||
| #define NBTK_ADJUSTMENT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_ADJUSTMENT, NbtkAdjustmentClass)) | ||||
|  | ||||
| typedef struct _NbtkAdjustment          NbtkAdjustment; | ||||
| typedef struct _NbtkAdjustmentPrivate   NbtkAdjustmentPrivate; | ||||
| typedef struct _NbtkAdjustmentClass     NbtkAdjustmentClass; | ||||
|  | ||||
| /** | ||||
|  * NbtkAdjustment: | ||||
|  * | ||||
|  * Class for handling an interval between to values. The contents of | ||||
|  * the #NbtkAdjustment are private and should be accessed using the | ||||
|  * public API. | ||||
|  */ | ||||
| struct _NbtkAdjustment | ||||
| { | ||||
|   /*< private >*/ | ||||
|   GObject parent_instance; | ||||
|  | ||||
|   NbtkAdjustmentPrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * NbtkAdjustmentClass | ||||
|  * @changed: Class handler for the ::changed signal. | ||||
|  * | ||||
|  * Base class for #NbtkAdjustment. | ||||
|  */ | ||||
| struct _NbtkAdjustmentClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   /*< public >*/ | ||||
|   void (* changed) (NbtkAdjustment *adjustment); | ||||
| }; | ||||
|  | ||||
| GType nbtk_adjustment_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| NbtkAdjustment *nbtk_adjustment_new          (gdouble         value, | ||||
|                                               gdouble         lower, | ||||
|                                               gdouble         upper, | ||||
|                                               gdouble         step_increment, | ||||
|                                               gdouble         page_increment, | ||||
|                                               gdouble         page_size); | ||||
| gdouble         nbtk_adjustment_get_value    (NbtkAdjustment *adjustment); | ||||
| void            nbtk_adjustment_set_value    (NbtkAdjustment *adjustment, | ||||
|                                               gdouble         value); | ||||
| void            nbtk_adjustment_clamp_page   (NbtkAdjustment *adjustment, | ||||
|                                               gdouble         lower, | ||||
|                                               gdouble         upper); | ||||
| void            nbtk_adjustment_set_values   (NbtkAdjustment *adjustment, | ||||
|                                               gdouble         value, | ||||
|                                               gdouble         lower, | ||||
|                                               gdouble         upper, | ||||
|                                               gdouble         step_increment, | ||||
|                                               gdouble         page_increment, | ||||
|                                               gdouble         page_size); | ||||
| void            nbtk_adjustment_get_values   (NbtkAdjustment *adjustment, | ||||
|                                               gdouble        *value, | ||||
|                                               gdouble        *lower, | ||||
|                                               gdouble        *upper, | ||||
|                                               gdouble        *step_increment, | ||||
|                                               gdouble        *page_increment, | ||||
|                                               gdouble        *page_size); | ||||
|  | ||||
| void            nbtk_adjustment_interpolate  (NbtkAdjustment *adjustment, | ||||
|                                               gdouble         value, | ||||
|                                               guint           duration); | ||||
|  | ||||
| gboolean        nbtk_adjustment_get_elastic  (NbtkAdjustment *adjustment); | ||||
| void            nbtk_adjustment_set_elastic  (NbtkAdjustment *adjustment, | ||||
|                                               gboolean        elastic); | ||||
|  | ||||
| gboolean        nbtk_adjustment_clamp        (NbtkAdjustment *adjustment, | ||||
|                                               gboolean        interpolate, | ||||
|                                               guint           duration); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_ADJUSTMENT_H__ */ | ||||
							
								
								
									
										739
									
								
								src/nbtk/nbtk-bin.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										739
									
								
								src/nbtk/nbtk-bin.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,739 @@ | ||||
| /* | ||||
|  * nbtk-bin.c: Basic container actor | ||||
|  * | ||||
|  * Copyright (c) 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Emmanuele Bassi <ebassi@linux.intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:nbtk-bin | ||||
|  * @short_description: a simple container with one actor | ||||
|  * | ||||
|  * #NbtkBin is a simple container capable of having only one | ||||
|  * #ClutterActor as a child. | ||||
|  * | ||||
|  * #NbtkBin inherits from #NbtkWidget, so it is fully themable. | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "nbtk-bin.h" | ||||
| #include "nbtk-enum-types.h" | ||||
| #include "nbtk-private.h" | ||||
|  | ||||
| #define NBTK_BIN_GET_PRIVATE(obj)       (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_BIN, NbtkBinPrivate)) | ||||
|  | ||||
| struct _NbtkBinPrivate | ||||
| { | ||||
|   ClutterActor *child; | ||||
|  | ||||
|   NbtkAlignment x_align; | ||||
|   NbtkAlignment y_align; | ||||
|  | ||||
|   guint x_fill : 1; | ||||
|   guint y_fill : 1; | ||||
| }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_CHILD, | ||||
|   PROP_X_ALIGN, | ||||
|   PROP_Y_ALIGN, | ||||
|   PROP_X_FILL, | ||||
|   PROP_Y_FILL | ||||
| }; | ||||
|  | ||||
| static void clutter_container_iface_init (ClutterContainerIface *iface); | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (NbtkBin, nbtk_bin, NBTK_TYPE_WIDGET, | ||||
|                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, | ||||
|                                                 clutter_container_iface_init)); | ||||
|  | ||||
| void | ||||
| _nbtk_bin_get_align_factors (NbtkBin *bin, | ||||
|                              gdouble *x_align, | ||||
|                              gdouble *y_align) | ||||
| { | ||||
|   NbtkBinPrivate *priv = bin->priv; | ||||
|   gdouble factor; | ||||
|  | ||||
|   switch (priv->x_align) | ||||
|     { | ||||
|     case NBTK_ALIGN_LEFT: | ||||
|       factor = 0.0; | ||||
|       break; | ||||
|  | ||||
|     case NBTK_ALIGN_CENTER: | ||||
|       factor = 0.5; | ||||
|       break; | ||||
|  | ||||
|     case NBTK_ALIGN_RIGHT: | ||||
|       factor = 1.0; | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       factor = 0.0; | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   if (x_align) | ||||
|     *x_align = factor; | ||||
|  | ||||
|   switch (priv->y_align) | ||||
|     { | ||||
|     case NBTK_ALIGN_TOP: | ||||
|       factor = 0.0; | ||||
|       break; | ||||
|  | ||||
|     case NBTK_ALIGN_CENTER: | ||||
|       factor = 0.5; | ||||
|       break; | ||||
|  | ||||
|     case NBTK_ALIGN_BOTTOM: | ||||
|       factor = 1.0; | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       factor = 0.0; | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   if (y_align) | ||||
|     *y_align = factor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_add (ClutterContainer *container, | ||||
|               ClutterActor     *actor) | ||||
| { | ||||
|   nbtk_bin_set_child (NBTK_BIN (container), actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_remove (ClutterContainer *container, | ||||
|                  ClutterActor     *actor) | ||||
| { | ||||
|   NbtkBinPrivate *priv = NBTK_BIN (container)->priv; | ||||
|  | ||||
|   if (priv->child == actor) | ||||
|     nbtk_bin_set_child (NBTK_BIN (container), NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_foreach (ClutterContainer *container, | ||||
|                   ClutterCallback   callback, | ||||
|                   gpointer          user_data) | ||||
| { | ||||
|   NbtkBinPrivate *priv = NBTK_BIN (container)->priv; | ||||
|  | ||||
|   if (priv->child) | ||||
|     callback (priv->child, user_data); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_container_iface_init (ClutterContainerIface *iface) | ||||
| { | ||||
|   iface->add = nbtk_bin_add; | ||||
|   iface->remove = nbtk_bin_remove; | ||||
|   iface->foreach = nbtk_bin_foreach; | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_paint (ClutterActor *self) | ||||
| { | ||||
|   NbtkBinPrivate *priv = NBTK_BIN (self)->priv; | ||||
|  | ||||
|   /* allow NbtkWidget to paint the background */ | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_bin_parent_class)->paint (self); | ||||
|  | ||||
|   /* the pain our child */ | ||||
|   if (priv->child) | ||||
|     clutter_actor_paint (priv->child); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_pick (ClutterActor       *self, | ||||
|                const ClutterColor *pick_color) | ||||
| { | ||||
|   NbtkBinPrivate *priv = NBTK_BIN (self)->priv; | ||||
|  | ||||
|   /* get the default pick implementation */ | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_bin_parent_class)->pick (self, pick_color); | ||||
|  | ||||
|   if (priv->child) | ||||
|     clutter_actor_paint (priv->child); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_allocate (ClutterActor          *self, | ||||
|                    const ClutterActorBox *box, | ||||
|                    ClutterAllocationFlags flags) | ||||
| { | ||||
|   NbtkBinPrivate *priv = NBTK_BIN (self)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_bin_parent_class)->allocate (self, box, | ||||
|                                                          flags); | ||||
|  | ||||
|   if (priv->child) | ||||
|     { | ||||
|       ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); | ||||
|       gfloat natural_width, natural_height; | ||||
|       gfloat min_width, min_height; | ||||
|       gfloat child_width, child_height; | ||||
|       gfloat available_width, available_height; | ||||
|       ClutterRequestMode request; | ||||
|       ClutterActorBox content_box; | ||||
|       ClutterActorBox allocation = { 0, }; | ||||
|       gdouble x_align, y_align; | ||||
|  | ||||
|       shell_theme_node_get_content_box (theme_node, box, &content_box); | ||||
|  | ||||
|       _nbtk_bin_get_align_factors (NBTK_BIN (self), &x_align, &y_align); | ||||
|  | ||||
|       available_width  = content_box.x2 - content_box.x1; | ||||
|       available_height = content_box.y2 - content_box.y1; | ||||
|  | ||||
|       if (available_width < 0) | ||||
|         available_width = 0; | ||||
|  | ||||
|       if (available_height < 0) | ||||
|         available_height = 0; | ||||
|  | ||||
|       if (priv->x_fill) | ||||
|         { | ||||
|           allocation.x1 = (int) content_box.x1; | ||||
|           allocation.x2 = (int) content_box.x2; | ||||
|         } | ||||
|  | ||||
|       if (priv->y_fill) | ||||
|         { | ||||
|           allocation.y1 = (int) content_box.y1; | ||||
|           allocation.y2 = (int) content_box.y2; | ||||
|         } | ||||
|  | ||||
|       /* if we are filling horizontally and vertically then we're done */ | ||||
|       if (priv->x_fill && priv->y_fill) | ||||
|         { | ||||
|           clutter_actor_allocate (priv->child, &allocation, flags); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|       request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH; | ||||
|       g_object_get (G_OBJECT (priv->child), "request-mode", &request, NULL); | ||||
|  | ||||
|       if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) | ||||
|         { | ||||
|           clutter_actor_get_preferred_width (priv->child, available_height, | ||||
|                                              &min_width, | ||||
|                                              &natural_width); | ||||
|  | ||||
|           child_width = CLAMP (natural_width, min_width, available_width); | ||||
|  | ||||
|           clutter_actor_get_preferred_height (priv->child, child_width, | ||||
|                                               &min_height, | ||||
|                                               &natural_height); | ||||
|  | ||||
|           child_height = CLAMP (natural_height, min_height, available_height); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           clutter_actor_get_preferred_height (priv->child, available_width, | ||||
|                                               &min_height, | ||||
|                                               &natural_height); | ||||
|  | ||||
|           child_height = CLAMP (natural_height, min_height, available_height); | ||||
|  | ||||
|           clutter_actor_get_preferred_width (priv->child, child_height, | ||||
|                                              &min_width, | ||||
|                                              &natural_width); | ||||
|  | ||||
|           child_width = CLAMP (natural_width, min_width, available_width); | ||||
|         } | ||||
|  | ||||
|       if (!priv->x_fill) | ||||
|         { | ||||
|           allocation.x1 = content_box.x1 + (int) ((available_width - child_width) * x_align); | ||||
|           allocation.x2 = allocation.x1 + child_width; | ||||
|         } | ||||
|  | ||||
|       if (!priv->y_fill) | ||||
|         { | ||||
|           allocation.y1 = content_box.y1 + (int) ((available_height - child_height) * y_align); | ||||
|           allocation.y2 = allocation.y1 + child_height; | ||||
|         } | ||||
|  | ||||
|       clutter_actor_allocate (priv->child, &allocation, flags); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_get_preferred_width (ClutterActor *self, | ||||
|                               gfloat   for_height, | ||||
|                               gfloat  *min_width_p, | ||||
|                               gfloat  *natural_width_p) | ||||
| { | ||||
|   NbtkBinPrivate *priv = NBTK_BIN (self)->priv; | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); | ||||
|  | ||||
|   shell_theme_node_adjust_for_height (theme_node, &for_height); | ||||
|  | ||||
|   if (priv->child == NULL) | ||||
|     { | ||||
|       if (min_width_p) | ||||
| 	*min_width_p = 0; | ||||
|  | ||||
|       if (natural_width_p) | ||||
|         *natural_width_p = 0; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       clutter_actor_get_preferred_width (priv->child, for_height, | ||||
|                                          min_width_p, | ||||
|                                          natural_width_p); | ||||
|     } | ||||
|  | ||||
|   shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_get_preferred_height (ClutterActor *self, | ||||
|                                gfloat   for_width, | ||||
|                                gfloat  *min_height_p, | ||||
|                                gfloat  *natural_height_p) | ||||
| { | ||||
|   NbtkBinPrivate *priv = NBTK_BIN (self)->priv; | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); | ||||
|  | ||||
|   shell_theme_node_adjust_for_width (theme_node, &for_width); | ||||
|  | ||||
|   if (priv->child == NULL) | ||||
|     { | ||||
|       if (min_height_p) | ||||
|         *min_height_p = 0; | ||||
|  | ||||
|       if (natural_height_p) | ||||
|         *natural_height_p = 0; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       clutter_actor_get_preferred_height (priv->child, for_width, | ||||
|                                           min_height_p, | ||||
|                                           natural_height_p); | ||||
|     } | ||||
|  | ||||
|   shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_dispose (GObject *gobject) | ||||
| { | ||||
|   NbtkBinPrivate *priv = NBTK_BIN (gobject)->priv; | ||||
|  | ||||
|   if (priv->child) | ||||
|     { | ||||
|       clutter_actor_unparent (priv->child); | ||||
|       priv->child = NULL; | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (nbtk_bin_parent_class)->dispose (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_set_property (GObject      *gobject, | ||||
|                        guint         prop_id, | ||||
|                        const GValue *value, | ||||
|                        GParamSpec   *pspec) | ||||
| { | ||||
|   NbtkBin *bin = NBTK_BIN (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_CHILD: | ||||
|       nbtk_bin_set_child (bin, g_value_get_object (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_X_ALIGN: | ||||
|       nbtk_bin_set_alignment (bin, | ||||
|                               g_value_get_enum (value), | ||||
|                               bin->priv->y_align); | ||||
|       break; | ||||
|  | ||||
|     case PROP_Y_ALIGN: | ||||
|       nbtk_bin_set_alignment (bin, | ||||
|                               bin->priv->x_align, | ||||
|                               g_value_get_enum (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_X_FILL: | ||||
|       nbtk_bin_set_fill (bin, | ||||
|                          g_value_get_boolean (value), | ||||
|                          bin->priv->y_fill); | ||||
|       break; | ||||
|  | ||||
|     case PROP_Y_FILL: | ||||
|       nbtk_bin_set_fill (bin, | ||||
|                          bin->priv->y_fill, | ||||
|                          g_value_get_boolean (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_get_property (GObject    *gobject, | ||||
|                        guint       prop_id, | ||||
|                        GValue     *value, | ||||
|                        GParamSpec *pspec) | ||||
| { | ||||
|   NbtkBinPrivate *priv = NBTK_BIN (gobject)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_CHILD: | ||||
|       g_value_set_object (value, priv->child); | ||||
|       break; | ||||
|  | ||||
|     case PROP_X_FILL: | ||||
|       g_value_set_boolean (value, priv->x_fill); | ||||
|       break; | ||||
|  | ||||
|     case PROP_Y_FILL: | ||||
|       g_value_set_boolean (value, priv->y_fill); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_class_init (NbtkBinClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (NbtkBinPrivate)); | ||||
|  | ||||
|   gobject_class->set_property = nbtk_bin_set_property; | ||||
|   gobject_class->get_property = nbtk_bin_get_property; | ||||
|   gobject_class->dispose = nbtk_bin_dispose; | ||||
|  | ||||
|   actor_class->get_preferred_width = nbtk_bin_get_preferred_width; | ||||
|   actor_class->get_preferred_height = nbtk_bin_get_preferred_height; | ||||
|   actor_class->allocate = nbtk_bin_allocate; | ||||
|   actor_class->paint = nbtk_bin_paint; | ||||
|   actor_class->pick = nbtk_bin_pick; | ||||
|  | ||||
|   /** | ||||
|    * NbtkBin:child: | ||||
|    * | ||||
|    * The child #ClutterActor of the #NbtkBin container. | ||||
|    */ | ||||
|   pspec = g_param_spec_object ("child", | ||||
|                                "Child", | ||||
|                                "The child of the Bin", | ||||
|                                CLUTTER_TYPE_ACTOR, | ||||
|                                NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_CHILD, pspec); | ||||
|  | ||||
|   /** | ||||
|    * NbtkBin:x-align: | ||||
|    * | ||||
|    * The horizontal alignment of the #NbtkBin child. | ||||
|    */ | ||||
|   pspec = g_param_spec_enum ("x-align", | ||||
|                              "X Align", | ||||
|                              "The horizontal alignment", | ||||
|                              NBTK_TYPE_ALIGNMENT, | ||||
|                              NBTK_ALIGN_CENTER, | ||||
|                              NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_X_ALIGN, pspec); | ||||
|  | ||||
|   /** | ||||
|    * NbtkBin:y-align: | ||||
|    * | ||||
|    * The vertical alignment of the #NbtkBin child. | ||||
|    */ | ||||
|   pspec = g_param_spec_enum ("y-align", | ||||
|                              "Y Align", | ||||
|                              "The vertical alignment", | ||||
|                              NBTK_TYPE_ALIGNMENT, | ||||
|                              NBTK_ALIGN_CENTER, | ||||
|                              NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_Y_ALIGN, pspec); | ||||
|  | ||||
|   /** | ||||
|    * NbtkBin:x-fill: | ||||
|    * | ||||
|    * Whether the child should fill the horizontal allocation | ||||
|    */ | ||||
|   pspec = g_param_spec_boolean ("x-fill", | ||||
|                                 "X Fill", | ||||
|                                 "Whether the child should fill the " | ||||
|                                 "horizontal allocation", | ||||
|                                 FALSE, | ||||
|                                 NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_X_FILL, pspec); | ||||
|  | ||||
|   /** | ||||
|    * NbtkBin:y-fill: | ||||
|    * | ||||
|    * Whether the child should fill the vertical allocation | ||||
|    */ | ||||
|   pspec = g_param_spec_boolean ("y-fill", | ||||
|                                 "Y Fill", | ||||
|                                 "Whether the child should fill the " | ||||
|                                 "vertical allocation", | ||||
|                                 FALSE, | ||||
|                                 NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_Y_FILL, pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_bin_init (NbtkBin *bin) | ||||
| { | ||||
|   bin->priv = NBTK_BIN_GET_PRIVATE (bin); | ||||
|  | ||||
|   bin->priv->x_align = NBTK_ALIGN_CENTER; | ||||
|   bin->priv->y_align = NBTK_ALIGN_CENTER; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_bin_new: | ||||
|  * | ||||
|  * Creates a new #NbtkBin, a simple container for one child. | ||||
|  * | ||||
|  * Return value: the newly created #NbtkBin actor | ||||
|  */ | ||||
| NbtkWidget * | ||||
| nbtk_bin_new (void) | ||||
| { | ||||
|   return g_object_new (NBTK_TYPE_BIN, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_bin_set_child: | ||||
|  * @bin: a #NbtkBin | ||||
|  * @child: a #ClutterActor, or %NULL | ||||
|  * | ||||
|  * Sets @child as the child of @bin. | ||||
|  * | ||||
|  * If @bin already has a child, the previous child is removed. | ||||
|  */ | ||||
| void | ||||
| nbtk_bin_set_child (NbtkBin *bin, | ||||
|                     ClutterActor *child) | ||||
| { | ||||
|   NbtkBinPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_BIN (bin)); | ||||
|   g_return_if_fail (child == NULL || CLUTTER_IS_ACTOR (child)); | ||||
|  | ||||
|   priv = bin->priv; | ||||
|  | ||||
|   if (priv->child == child) | ||||
|     return; | ||||
|  | ||||
|   if (priv->child) | ||||
|     { | ||||
|       ClutterActor *old_child = priv->child; | ||||
|  | ||||
|       g_object_ref (old_child); | ||||
|  | ||||
|       priv->child = NULL; | ||||
|       clutter_actor_unparent (old_child); | ||||
|  | ||||
|       g_signal_emit_by_name (bin, "actor-removed", old_child); | ||||
|  | ||||
|       g_object_unref (old_child); | ||||
|     } | ||||
|  | ||||
|   if (child) | ||||
|     { | ||||
|       priv->child = child; | ||||
|       clutter_actor_set_parent (child, CLUTTER_ACTOR (bin)); | ||||
|  | ||||
|       g_signal_emit_by_name (bin, "actor-added", priv->child); | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_relayout (CLUTTER_ACTOR (bin)); | ||||
|  | ||||
|   g_object_notify (G_OBJECT (bin), "child"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_bin_get_child: | ||||
|  * @bin: a #NbtkBin | ||||
|  * | ||||
|  * Retrieves a pointer to the child of @bin. | ||||
|  * | ||||
|  * Return value: (transfer none): a #ClutterActor, or %NULL | ||||
|  */ | ||||
| ClutterActor * | ||||
| nbtk_bin_get_child (NbtkBin *bin) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_BIN (bin), NULL); | ||||
|  | ||||
|   return bin->priv->child; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_bin_set_alignment: | ||||
|  * @bin: a #NbtkBin | ||||
|  * @x_align: horizontal alignment | ||||
|  * @y_align: vertical alignment | ||||
|  * | ||||
|  * Sets the horizontal and vertical alignment of the child | ||||
|  * inside a #NbtkBin. | ||||
|  */ | ||||
| void | ||||
| nbtk_bin_set_alignment (NbtkBin       *bin, | ||||
|                         NbtkAlignment  x_align, | ||||
|                         NbtkAlignment  y_align) | ||||
| { | ||||
|   NbtkBinPrivate *priv; | ||||
|   gboolean changed = FALSE; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_BIN (bin)); | ||||
|  | ||||
|   priv = bin->priv; | ||||
|  | ||||
|   g_object_freeze_notify (G_OBJECT (bin)); | ||||
|  | ||||
|   if (priv->x_align != x_align) | ||||
|     { | ||||
|       priv->x_align = x_align; | ||||
|       g_object_notify (G_OBJECT (bin), "x-align"); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (priv->y_align != y_align) | ||||
|     { | ||||
|       priv->y_align = y_align; | ||||
|       g_object_notify (G_OBJECT (bin), "y-align"); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (changed) | ||||
|     clutter_actor_queue_relayout (CLUTTER_ACTOR (bin)); | ||||
|  | ||||
|   g_object_thaw_notify (G_OBJECT (bin)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_bin_get_alignment: | ||||
|  * @bin: a #NbtkBin | ||||
|  * @x_align: return location for the horizontal alignment, or %NULL | ||||
|  * @y_align: return location for the vertical alignment, or %NULL | ||||
|  * | ||||
|  * Retrieves the horizontal and vertical alignment of the child | ||||
|  * inside a #NbtkBin, as set by nbtk_bin_set_alignment(). | ||||
|  */ | ||||
| void | ||||
| nbtk_bin_get_alignment (NbtkBin       *bin, | ||||
|                         NbtkAlignment *x_align, | ||||
|                         NbtkAlignment *y_align) | ||||
| { | ||||
|   NbtkBinPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_BIN (bin)); | ||||
|  | ||||
|   priv = bin->priv; | ||||
|  | ||||
|   if (x_align) | ||||
|     *x_align = priv->x_align; | ||||
|  | ||||
|   if (y_align) | ||||
|     *y_align = priv->y_align; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_bin_set_fill: | ||||
|  * @bin: a #NbtkBin | ||||
|  * @x_fill: %TRUE if the child should fill horizontally the @bin | ||||
|  * @y_fill: %TRUE if the child should fill vertically the @bin | ||||
|  * | ||||
|  * Sets whether the child of @bin should fill out the horizontal | ||||
|  * and/or vertical allocation of the parent | ||||
|  */ | ||||
| void | ||||
| nbtk_bin_set_fill (NbtkBin  *bin, | ||||
|                    gboolean  x_fill, | ||||
|                    gboolean  y_fill) | ||||
| { | ||||
|   NbtkBinPrivate *priv; | ||||
|   gboolean changed = FALSE; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_BIN (bin)); | ||||
|  | ||||
|   priv = bin->priv; | ||||
|  | ||||
|   g_object_freeze_notify (G_OBJECT (bin)); | ||||
|  | ||||
|   if (priv->x_fill != x_fill) | ||||
|     { | ||||
|       priv->x_fill = x_fill; | ||||
|       changed = TRUE; | ||||
|  | ||||
|       g_object_notify (G_OBJECT (bin), "x-fill"); | ||||
|     } | ||||
|  | ||||
|   if (priv->y_fill != y_fill) | ||||
|     { | ||||
|       priv->y_fill = y_fill; | ||||
|       changed = TRUE; | ||||
|  | ||||
|       g_object_notify (G_OBJECT (bin), "y-fill"); | ||||
|     } | ||||
|  | ||||
|   if (changed) | ||||
|     clutter_actor_queue_relayout (CLUTTER_ACTOR (bin)); | ||||
|  | ||||
|   g_object_thaw_notify (G_OBJECT (bin)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_bin_get_fill: | ||||
|  * @bin: a #NbtkBin | ||||
|  * @x_fill: (out): return location for the horizontal fill, or %NULL | ||||
|  * @y_fill: (out): return location for the vertical fill, or %NULL | ||||
|  * | ||||
|  * Retrieves the horizontal and vertical fill settings | ||||
|  */ | ||||
| void | ||||
| nbtk_bin_get_fill (NbtkBin  *bin, | ||||
|                    gboolean *x_fill, | ||||
|                    gboolean *y_fill) | ||||
| { | ||||
|   g_return_if_fail (NBTK_IS_BIN (bin)); | ||||
|  | ||||
|   if (x_fill) | ||||
|     *x_fill = bin->priv->x_fill; | ||||
|  | ||||
|   if (y_fill) | ||||
|     *y_fill = bin->priv->y_fill; | ||||
| } | ||||
							
								
								
									
										92
									
								
								src/nbtk/nbtk-bin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/nbtk/nbtk-bin.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| /* | ||||
|  * nbtk-bin.h: Basic container actor | ||||
|  * | ||||
|  * Copyright 2009, 2008 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: Emmanuele Bassi <ebassi@linux.intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_BIN_H__ | ||||
| #define __NBTK_BIN_H__ | ||||
|  | ||||
| #include <nbtk/nbtk-types.h> | ||||
| #include <nbtk/nbtk-widget.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_BIN                   (nbtk_bin_get_type ()) | ||||
| #define NBTK_BIN(obj)                   (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_BIN, NbtkBin)) | ||||
| #define NBTK_IS_BIN(obj)                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_BIN)) | ||||
| #define NBTK_BIN_CLASS(klass)           (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_BIN, NbtkBinClass)) | ||||
| #define NBTK_IS_BIN_CLASS(klass)        (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_BIN)) | ||||
| #define NBTK_BIN_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_BIN, NbtkBinClass)) | ||||
|  | ||||
| typedef struct _NbtkBin                 NbtkBin; | ||||
| typedef struct _NbtkBinPrivate          NbtkBinPrivate; | ||||
| typedef struct _NbtkBinClass            NbtkBinClass; | ||||
|  | ||||
| /** | ||||
|  * NbtkBin: | ||||
|  * | ||||
|  * The #NbtkBin struct contains only private data | ||||
|  */ | ||||
| struct _NbtkBin | ||||
| { | ||||
|   /*< private >*/ | ||||
|   NbtkWidget parent_instance; | ||||
|  | ||||
|   NbtkBinPrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * NbtkBinClass: | ||||
|  * | ||||
|  * The #NbtkBinClass struct contains only private data | ||||
|  */ | ||||
| struct _NbtkBinClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   NbtkWidgetClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType nbtk_bin_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| NbtkWidget   *nbtk_bin_new           (void); | ||||
| void          nbtk_bin_set_child     (NbtkBin           *bin, | ||||
|                                       ClutterActor      *child); | ||||
| ClutterActor *nbtk_bin_get_child     (NbtkBin           *bin); | ||||
| void          nbtk_bin_set_alignment (NbtkBin           *bin, | ||||
|                                       NbtkAlignment      x_align, | ||||
|                                       NbtkAlignment      y_align); | ||||
| void          nbtk_bin_get_alignment (NbtkBin           *bin, | ||||
|                                       NbtkAlignment     *x_align, | ||||
|                                       NbtkAlignment     *y_align); | ||||
| void          nbtk_bin_set_fill      (NbtkBin           *bin, | ||||
|                                       gboolean           x_fill, | ||||
|                                       gboolean           y_fill); | ||||
| void          nbtk_bin_get_fill      (NbtkBin           *bin, | ||||
|                                       gboolean          *x_fill, | ||||
|                                       gboolean          *y_fill); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_BIN_H__ */ | ||||
							
								
								
									
										176
									
								
								src/nbtk/nbtk-box-layout-child.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								src/nbtk/nbtk-box-layout-child.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | ||||
| /* | ||||
|  * nbtk-box-layout-child.c: box layout child actor | ||||
|  * | ||||
|  * Copyright 2009 Intel Corporation | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Thomas Wood <thomas.wood@intel.com> | ||||
|  */ | ||||
|  | ||||
| #include "nbtk-box-layout-child.h" | ||||
| #include "nbtk-private.h" | ||||
|  | ||||
| G_DEFINE_TYPE (NbtkBoxLayoutChild, nbtk_box_layout_child, CLUTTER_TYPE_CHILD_META) | ||||
|  | ||||
| #define BOX_LAYOUT_CHILD_PRIVATE(o) \ | ||||
|   (G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChildPrivate)) | ||||
|  | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_EXPAND, | ||||
|   PROP_X_FILL, | ||||
|   PROP_Y_FILL, | ||||
|   PROP_X_ALIGN, | ||||
|   PROP_Y_ALIGN | ||||
| }; | ||||
|  | ||||
| static void | ||||
| nbtk_box_layout_child_get_property (GObject *object, guint property_id, | ||||
|                                     GValue *value, GParamSpec *pspec) | ||||
| { | ||||
|   NbtkBoxLayoutChild *child = NBTK_BOX_LAYOUT_CHILD (object); | ||||
|  | ||||
|   switch (property_id) | ||||
|     { | ||||
|     case PROP_EXPAND: | ||||
|       g_value_set_boolean (value, child->expand); | ||||
|       break; | ||||
|     case PROP_X_FILL: | ||||
|       g_value_set_boolean (value, child->x_fill); | ||||
|       break; | ||||
|     case PROP_Y_FILL: | ||||
|       g_value_set_boolean (value, child->y_fill); | ||||
|       break; | ||||
|     case PROP_X_ALIGN: | ||||
|       g_value_set_enum (value, child->x_align); | ||||
|       break; | ||||
|     case PROP_Y_ALIGN: | ||||
|       g_value_set_enum (value, child->y_align); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_box_layout_child_set_property (GObject *object, guint property_id, | ||||
|                                     const GValue *value, GParamSpec *pspec) | ||||
| { | ||||
|   NbtkBoxLayoutChild *child = NBTK_BOX_LAYOUT_CHILD (object); | ||||
|   NbtkBoxLayout *box = NBTK_BOX_LAYOUT (CLUTTER_CHILD_META (object)->container); | ||||
|  | ||||
|   switch (property_id) | ||||
|     { | ||||
|     case PROP_EXPAND: | ||||
|       child->expand = g_value_get_boolean (value); | ||||
|       break; | ||||
|     case PROP_X_FILL: | ||||
|       child->x_fill = g_value_get_boolean (value); | ||||
|       break; | ||||
|     case PROP_Y_FILL: | ||||
|       child->y_fill = g_value_get_boolean (value); | ||||
|       break; | ||||
|     case PROP_X_ALIGN: | ||||
|       child->x_align = g_value_get_enum (value); | ||||
|       break; | ||||
|     case PROP_Y_ALIGN: | ||||
|       child->y_align = g_value_get_enum (value); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_relayout ((ClutterActor*) box); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_box_layout_child_dispose (GObject *object) | ||||
| { | ||||
|   G_OBJECT_CLASS (nbtk_box_layout_child_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_box_layout_child_finalize (GObject *object) | ||||
| { | ||||
|   G_OBJECT_CLASS (nbtk_box_layout_child_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_box_layout_child_class_init (NbtkBoxLayoutChildClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   object_class->get_property = nbtk_box_layout_child_get_property; | ||||
|   object_class->set_property = nbtk_box_layout_child_set_property; | ||||
|   object_class->dispose = nbtk_box_layout_child_dispose; | ||||
|   object_class->finalize = nbtk_box_layout_child_finalize; | ||||
|  | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("expand", "Expand", | ||||
|                                 "Allocate the child extra space", | ||||
|                                 FALSE, | ||||
|                                 NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (object_class, PROP_EXPAND, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("x-fill", "x-fill", | ||||
|                                 "Whether the child should receive priority " | ||||
|                                 "when the container is allocating spare space " | ||||
|                                 "on the horizontal axis", | ||||
|                                 TRUE, | ||||
|                                 NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (object_class, PROP_X_FILL, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("y-fill", "y-fill", | ||||
|                                 "Whether the child should receive priority " | ||||
|                                 "when the container is allocating spare space " | ||||
|                                 "on the vertical axis", | ||||
|                                 TRUE, | ||||
|                                 NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (object_class, PROP_Y_FILL, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_enum ("x-align", | ||||
|                              "X Alignment", | ||||
|                              "X alignment of the widget within the cell", | ||||
|                              NBTK_TYPE_ALIGN, | ||||
|                              NBTK_ALIGN_MIDDLE, | ||||
|                              NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (object_class, PROP_X_ALIGN, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_enum ("y-align", | ||||
|                              "Y Alignment", | ||||
|                              "Y alignment of the widget within the cell", | ||||
|                              NBTK_TYPE_ALIGN, | ||||
|                              NBTK_ALIGN_MIDDLE, | ||||
|                              NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (object_class, PROP_Y_ALIGN, pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_box_layout_child_init (NbtkBoxLayoutChild *self) | ||||
| { | ||||
|   self->expand = FALSE; | ||||
|  | ||||
|   self->x_fill = TRUE; | ||||
|   self->y_fill = TRUE; | ||||
|  | ||||
|   self->x_align = NBTK_ALIGN_CENTER; | ||||
|   self->y_align = NBTK_ALIGN_CENTER; | ||||
| } | ||||
							
								
								
									
										84
									
								
								src/nbtk/nbtk-box-layout-child.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/nbtk/nbtk-box-layout-child.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| /* | ||||
|  * nbtk-box-layout-child.h: box layout child actor | ||||
|  * | ||||
|  * Copyright 2009 Intel Corporation | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Thomas Wood <thomas.wood@intel.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef _NBTK_BOX_LAYOUT_CHILD_H | ||||
| #define _NBTK_BOX_LAYOUT_CHILD_H | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include "nbtk-enum-types.h" | ||||
| #include "nbtk-box-layout.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_BOX_LAYOUT_CHILD nbtk_box_layout_child_get_type() | ||||
|  | ||||
| #define NBTK_BOX_LAYOUT_CHILD(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ | ||||
|   NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChild)) | ||||
|  | ||||
| #define NBTK_BOX_LAYOUT_CHILD_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_CAST ((klass), \ | ||||
|   NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChildClass)) | ||||
|  | ||||
| #define NBTK_IS_BOX_LAYOUT_CHILD(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ | ||||
|   NBTK_TYPE_BOX_LAYOUT_CHILD)) | ||||
|  | ||||
| #define NBTK_IS_BOX_LAYOUT_CHILD_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_TYPE ((klass), \ | ||||
|   NBTK_TYPE_BOX_LAYOUT_CHILD)) | ||||
|  | ||||
| #define NBTK_BOX_LAYOUT_CHILD_GET_CLASS(obj) \ | ||||
|   (G_TYPE_INSTANCE_GET_CLASS ((obj), \ | ||||
|   NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChildClass)) | ||||
|  | ||||
| typedef struct _NbtkBoxLayoutChild NbtkBoxLayoutChild; | ||||
| typedef struct _NbtkBoxLayoutChildClass NbtkBoxLayoutChildClass; | ||||
| typedef struct _NbtkBoxLayoutChildPrivate NbtkBoxLayoutChildPrivate; | ||||
|  | ||||
| /** | ||||
|  * NbtkBoxLayoutChild: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _NbtkBoxLayoutChild | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterChildMeta parent; | ||||
|  | ||||
|   gboolean expand; | ||||
|   gboolean x_fill : 1; | ||||
|   gboolean y_fill : 1; | ||||
|   NbtkAlign x_align; | ||||
|   NbtkAlign y_align; | ||||
| }; | ||||
|  | ||||
| struct _NbtkBoxLayoutChildClass | ||||
| { | ||||
|   ClutterChildMetaClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType nbtk_box_layout_child_get_type (void); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* _NBTK_BOX_LAYOUT_CHILD_H */ | ||||
							
								
								
									
										1252
									
								
								src/nbtk/nbtk-box-layout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1252
									
								
								src/nbtk/nbtk-box-layout.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										91
									
								
								src/nbtk/nbtk-box-layout.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/nbtk/nbtk-box-layout.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| /* | ||||
|  * nbtk-box-layout.h: box layout actor | ||||
|  * | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Thomas Wood <thomas.wood@intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #ifndef _NBTK_BOX_LAYOUT_H | ||||
| #define _NBTK_BOX_LAYOUT_H | ||||
|  | ||||
| #include <nbtk/nbtk-widget.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_BOX_LAYOUT nbtk_box_layout_get_type() | ||||
|  | ||||
| #define NBTK_BOX_LAYOUT(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ | ||||
|   NBTK_TYPE_BOX_LAYOUT, NbtkBoxLayout)) | ||||
|  | ||||
| #define NBTK_BOX_LAYOUT_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_CAST ((klass), \ | ||||
|   NBTK_TYPE_BOX_LAYOUT, NbtkBoxLayoutClass)) | ||||
|  | ||||
| #define NBTK_IS_BOX_LAYOUT(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ | ||||
|   NBTK_TYPE_BOX_LAYOUT)) | ||||
|  | ||||
| #define NBTK_IS_BOX_LAYOUT_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_TYPE ((klass), \ | ||||
|   NBTK_TYPE_BOX_LAYOUT)) | ||||
|  | ||||
| #define NBTK_BOX_LAYOUT_GET_CLASS(obj) \ | ||||
|   (G_TYPE_INSTANCE_GET_CLASS ((obj), \ | ||||
|   NBTK_TYPE_BOX_LAYOUT, NbtkBoxLayoutClass)) | ||||
|  | ||||
| typedef struct _NbtkBoxLayout NbtkBoxLayout; | ||||
| typedef struct _NbtkBoxLayoutClass NbtkBoxLayoutClass; | ||||
| typedef struct _NbtkBoxLayoutPrivate NbtkBoxLayoutPrivate; | ||||
|  | ||||
| /** | ||||
|  * NbtkBoxLayout: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _NbtkBoxLayout | ||||
| { | ||||
|   /*< private >*/ | ||||
|   NbtkWidget parent; | ||||
|  | ||||
|   NbtkBoxLayoutPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _NbtkBoxLayoutClass | ||||
| { | ||||
|   NbtkWidgetClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType nbtk_box_layout_get_type (void); | ||||
|  | ||||
| NbtkWidget *nbtk_box_layout_new (void); | ||||
|  | ||||
| void nbtk_box_layout_set_vertical (NbtkBoxLayout *box, gboolean vertical); | ||||
| gboolean nbtk_box_layout_get_vertical (NbtkBoxLayout *box); | ||||
|  | ||||
| void nbtk_box_layout_set_pack_start (NbtkBoxLayout *box, gboolean pack_start); | ||||
| gboolean nbtk_box_layout_get_pack_start (NbtkBoxLayout *box); | ||||
|  | ||||
| void nbtk_box_layout_set_spacing (NbtkBoxLayout *box, guint spacing); | ||||
| guint nbtk_box_layout_get_spacing (NbtkBoxLayout *box); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* _NBTK_BOX_LAYOUT_H */ | ||||
							
								
								
									
										690
									
								
								src/nbtk/nbtk-button.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										690
									
								
								src/nbtk/nbtk-button.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,690 @@ | ||||
| /*-button.c: Plain button actor | ||||
|  * Copyright 2007 OpenedHand | ||||
|  * Copyright , 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Emmanuele Bassi <ebassi@openedhand.com> | ||||
|  *             Thomas Wood <thomas@linux.intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:nbtk-button | ||||
|  * @short_description: Button widget | ||||
|  * | ||||
|  * A button widget with support for either a text label or icon, toggle mode | ||||
|  * and transitions effects between states. | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <math.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include <glib.h> | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "nbtk-button.h" | ||||
|  | ||||
| #include "nbtk-marshal.h" | ||||
| #include "nbtk-texture-frame.h" | ||||
| #include "nbtk-texture-cache.h" | ||||
| #include "nbtk-private.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_LABEL, | ||||
|   PROP_TOGGLE, | ||||
|   PROP_ACTIVE, | ||||
|   PROP_TRANSITION | ||||
| }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   CLICKED, | ||||
|  | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| #define NBTK_BUTTON_GET_PRIVATE(obj)    \ | ||||
|         (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_BUTTON, NbtkButtonPrivate)) | ||||
|  | ||||
| struct _NbtkButtonPrivate | ||||
| { | ||||
|   gchar *text; | ||||
|  | ||||
|   ClutterActor *old_bg; | ||||
|   gboolean old_bg_parented; /* TRUE if we have adopted old_bg */ | ||||
|  | ||||
|   guint8 old_opacity; | ||||
|  | ||||
|   guint is_pressed : 1; | ||||
|   guint is_hover : 1; | ||||
|   guint is_checked : 1; | ||||
|   guint is_toggle : 1; | ||||
|  | ||||
|   gint transition_duration; | ||||
|  | ||||
|   ClutterAnimation *animation; | ||||
|  | ||||
|   gint spacing; | ||||
| }; | ||||
|  | ||||
| static guint button_signals[LAST_SIGNAL] = { 0, }; | ||||
|  | ||||
| G_DEFINE_TYPE (NbtkButton, nbtk_button, NBTK_TYPE_BIN); | ||||
|  | ||||
| static void | ||||
| nbtk_button_update_label_style (NbtkButton *button) | ||||
| { | ||||
|   ClutterActor *label; | ||||
|   ShellThemeNode *theme_node; | ||||
|   ClutterColor color; | ||||
|   const PangoFontDescription *font; | ||||
|   gchar *font_string = NULL; | ||||
|  | ||||
|   label = nbtk_bin_get_child ((NbtkBin*) button); | ||||
|  | ||||
|   /* check the child is really a label */ | ||||
|   if (!CLUTTER_IS_TEXT (label)) | ||||
|     return; | ||||
|  | ||||
|   theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (button)); | ||||
|  | ||||
|   shell_theme_node_get_foreground_color (theme_node, &color); | ||||
|   clutter_text_set_color (CLUTTER_TEXT (label), &color); | ||||
|  | ||||
|   font = shell_theme_node_get_font (theme_node); | ||||
|   font_string = pango_font_description_to_string (font); | ||||
|   clutter_text_set_font_name (CLUTTER_TEXT (label), font_string); | ||||
|   g_free (font_string); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_dispose_old_bg (NbtkButton *button) | ||||
| { | ||||
|   NbtkButtonPrivate *priv = button->priv; | ||||
|  | ||||
|   if (priv->old_bg) | ||||
|     { | ||||
|       if (priv->old_bg_parented) | ||||
|         { | ||||
|           clutter_actor_unparent (priv->old_bg); | ||||
|           priv->old_bg_parented = FALSE; | ||||
|         } | ||||
|       g_object_unref (priv->old_bg); | ||||
|       priv->old_bg = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_animation_completed (ClutterAnimation  *animation, | ||||
|                           NbtkButton        *button) | ||||
| { | ||||
|   nbtk_button_dispose_old_bg (button); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_style_changed (NbtkWidget *widget) | ||||
| { | ||||
|   NbtkButton *button = NBTK_BUTTON (widget); | ||||
|   NbtkButtonPrivate *priv = button->priv; | ||||
|   NbtkButtonClass *button_class = NBTK_BUTTON_GET_CLASS (button); | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (button)); | ||||
|   ClutterActor *bg_image; | ||||
|   double spacing; | ||||
|  | ||||
|   nbtk_button_dispose_old_bg (button); | ||||
|  | ||||
|   bg_image = nbtk_widget_get_border_image ((NbtkWidget*) button); | ||||
|   if (bg_image) | ||||
|     button->priv->old_bg = g_object_ref (bg_image); | ||||
|  | ||||
|   NBTK_WIDGET_CLASS (nbtk_button_parent_class)->style_changed (widget); | ||||
|  | ||||
|   spacing = 6; | ||||
|   shell_theme_node_get_length (theme_node, "border-spacing", FALSE, &spacing); | ||||
|   priv->spacing = round (spacing); | ||||
|  | ||||
|   /* update the label styling */ | ||||
|   nbtk_button_update_label_style (button); | ||||
|  | ||||
|   /* run a transition if applicable */ | ||||
|   if (button_class->transition) | ||||
|     { | ||||
|       button_class->transition (button, priv->old_bg); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (priv->old_bg && | ||||
|           (!nbtk_widget_get_style_pseudo_class (widget))) | ||||
|         { | ||||
|           ClutterAnimation *animation; | ||||
|           if (!clutter_actor_get_parent (priv->old_bg)) | ||||
|             { | ||||
|               clutter_actor_set_parent (priv->old_bg, (ClutterActor*) widget); | ||||
|               priv->old_bg_parented = TRUE; | ||||
|             } | ||||
|           if (priv->transition_duration > 0) | ||||
|             { | ||||
|               animation = clutter_actor_animate (priv->old_bg, | ||||
|                                                  CLUTTER_LINEAR, | ||||
|                                                  priv->transition_duration, | ||||
|                                                  "opacity", 0, | ||||
|                                                  NULL); | ||||
|               g_signal_connect (animation, "completed", | ||||
|                                 G_CALLBACK (nbtk_animation_completed), button); | ||||
|             } | ||||
|           else | ||||
|             { | ||||
|               nbtk_button_dispose_old_bg (button); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_real_pressed (NbtkButton *button) | ||||
| { | ||||
|   nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "active"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_real_released (NbtkButton *button) | ||||
| { | ||||
|   NbtkButtonPrivate *priv = button->priv; | ||||
|  | ||||
|   if (priv->is_checked) | ||||
|     nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "checked"); | ||||
|   else if (!priv->is_hover) | ||||
|     nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, NULL); | ||||
|   else | ||||
|     nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "hover"); | ||||
|  | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| nbtk_button_button_press (ClutterActor       *actor, | ||||
|                           ClutterButtonEvent *event) | ||||
| { | ||||
|   nbtk_widget_hide_tooltip (NBTK_WIDGET (actor)); | ||||
|  | ||||
|   if (event->button == 1) | ||||
|     { | ||||
|       NbtkButton *button = NBTK_BUTTON (actor); | ||||
|       NbtkButtonClass *klass = NBTK_BUTTON_GET_CLASS (button); | ||||
|  | ||||
|       button->priv->is_pressed = TRUE; | ||||
|  | ||||
|       clutter_grab_pointer (actor); | ||||
|  | ||||
|       if (klass->pressed) | ||||
|         klass->pressed (button); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| nbtk_button_button_release (ClutterActor       *actor, | ||||
|                             ClutterButtonEvent *event) | ||||
| { | ||||
|   if (event->button == 1) | ||||
|     { | ||||
|       NbtkButton *button = NBTK_BUTTON (actor); | ||||
|       NbtkButtonClass *klass = NBTK_BUTTON_GET_CLASS (button); | ||||
|  | ||||
|       if (!button->priv->is_pressed) | ||||
|         return FALSE; | ||||
|  | ||||
|       clutter_ungrab_pointer (); | ||||
|  | ||||
|       if (button->priv->is_toggle) | ||||
|         { | ||||
|           nbtk_button_set_checked (button, !button->priv->is_checked); | ||||
|         } | ||||
|  | ||||
|       button->priv->is_pressed = FALSE; | ||||
|  | ||||
|       if (klass->released) | ||||
|         klass->released (button); | ||||
|  | ||||
|       g_signal_emit (button, button_signals[CLICKED], 0); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| nbtk_button_enter (ClutterActor         *actor, | ||||
|                    ClutterCrossingEvent *event) | ||||
| { | ||||
|   NbtkButton *button = NBTK_BUTTON (actor); | ||||
|  | ||||
|   if (!button->priv->is_checked) | ||||
|     nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "hover"); | ||||
|  | ||||
|   button->priv->is_hover = 1; | ||||
|  | ||||
|   return CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->enter_event (actor, event); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| nbtk_button_leave (ClutterActor         *actor, | ||||
|                    ClutterCrossingEvent *event) | ||||
| { | ||||
|   NbtkButton *button = NBTK_BUTTON (actor); | ||||
|  | ||||
|   button->priv->is_hover = 0; | ||||
|  | ||||
|   if (button->priv->is_pressed) | ||||
|     { | ||||
|       NbtkButtonClass *klass = NBTK_BUTTON_GET_CLASS (button); | ||||
|  | ||||
|       clutter_ungrab_pointer (); | ||||
|  | ||||
|       button->priv->is_pressed = FALSE; | ||||
|  | ||||
|       if (klass->released) | ||||
|         klass->released (button); | ||||
|     } | ||||
|  | ||||
|   if (button->priv->is_checked) | ||||
|     nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "checked"); | ||||
|   else | ||||
|     nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, NULL); | ||||
|  | ||||
|   return CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->leave_event (actor, event); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_set_property (GObject      *gobject, | ||||
|                           guint         prop_id, | ||||
|                           const GValue *value, | ||||
|                           GParamSpec   *pspec) | ||||
| { | ||||
|   NbtkButton *button = NBTK_BUTTON (gobject); | ||||
|   NbtkButtonPrivate *priv = NBTK_BUTTON (gobject)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_LABEL: | ||||
|       nbtk_button_set_label (button, g_value_get_string (value)); | ||||
|       break; | ||||
|     case PROP_TOGGLE: | ||||
|       nbtk_button_set_toggle_mode (button, g_value_get_boolean (value)); | ||||
|       break; | ||||
|     case PROP_ACTIVE: | ||||
|       nbtk_button_set_checked (button, g_value_get_boolean (value)); | ||||
|       break; | ||||
|     case PROP_TRANSITION: | ||||
|       priv->transition_duration = g_value_get_int (value); | ||||
|       break; | ||||
|  | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_get_property (GObject    *gobject, | ||||
|                           guint       prop_id, | ||||
|                           GValue     *value, | ||||
|                           GParamSpec *pspec) | ||||
| { | ||||
|   NbtkButtonPrivate *priv = NBTK_BUTTON (gobject)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_LABEL: | ||||
|       g_value_set_string (value, priv->text); | ||||
|       break; | ||||
|     case PROP_TOGGLE: | ||||
|       g_value_set_boolean (value, priv->is_toggle); | ||||
|       break; | ||||
|     case PROP_ACTIVE: | ||||
|       g_value_set_boolean (value, priv->is_checked); | ||||
|       break; | ||||
|     case PROP_TRANSITION: | ||||
|       g_value_set_int (value, priv->transition_duration); | ||||
|       break; | ||||
|  | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_finalize (GObject *gobject) | ||||
| { | ||||
|   NbtkButtonPrivate *priv = NBTK_BUTTON (gobject)->priv; | ||||
|  | ||||
|   g_free (priv->text); | ||||
|  | ||||
|   G_OBJECT_CLASS (nbtk_button_parent_class)->finalize (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_dispose (GObject *gobject) | ||||
| { | ||||
|   nbtk_button_dispose_old_bg (NBTK_BUTTON (gobject)); | ||||
|  | ||||
|   G_OBJECT_CLASS (nbtk_button_parent_class)->dispose (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_map (ClutterActor *self) | ||||
| { | ||||
|   NbtkButtonPrivate *priv = NBTK_BUTTON (self)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->map (self); | ||||
|  | ||||
|   if (priv->old_bg && priv->old_bg_parented) | ||||
|     clutter_actor_map (priv->old_bg); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_unmap (ClutterActor *self) | ||||
| { | ||||
|   NbtkButtonPrivate *priv = NBTK_BUTTON (self)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->unmap (self); | ||||
|  | ||||
|   if (priv->old_bg && priv->old_bg_parented) | ||||
|     clutter_actor_unmap (priv->old_bg); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_draw_background (NbtkWidget         *widget) | ||||
| { | ||||
|   NbtkButtonPrivate *priv; | ||||
|  | ||||
|   NBTK_WIDGET_CLASS (nbtk_button_parent_class)->draw_background (widget); | ||||
|  | ||||
|   priv = NBTK_BUTTON (widget)->priv; | ||||
|  | ||||
|   if (priv->old_bg && priv->old_bg_parented) | ||||
|       clutter_actor_paint (priv->old_bg); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_class_init (NbtkButtonClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (NbtkButtonPrivate)); | ||||
|  | ||||
|   klass->pressed = nbtk_button_real_pressed; | ||||
|   klass->released = nbtk_button_real_released; | ||||
|  | ||||
|   gobject_class->set_property = nbtk_button_set_property; | ||||
|   gobject_class->get_property = nbtk_button_get_property; | ||||
|   gobject_class->dispose = nbtk_button_dispose; | ||||
|   gobject_class->finalize = nbtk_button_finalize; | ||||
|  | ||||
|   actor_class->button_press_event = nbtk_button_button_press; | ||||
|   actor_class->button_release_event = nbtk_button_button_release; | ||||
|   actor_class->enter_event = nbtk_button_enter; | ||||
|   actor_class->leave_event = nbtk_button_leave; | ||||
|  | ||||
|   actor_class->map = nbtk_button_map; | ||||
|   actor_class->unmap = nbtk_button_unmap; | ||||
|  | ||||
|   widget_class->draw_background = nbtk_button_draw_background; | ||||
|   widget_class->style_changed = nbtk_button_style_changed; | ||||
|  | ||||
|   pspec = g_param_spec_string ("label", | ||||
|                                "Label", | ||||
|                                "Label of the button", | ||||
|                                NULL, G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_LABEL, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("toggle-mode", | ||||
|                                 "Toggle Mode", | ||||
|                                 "Enable or disable toggling", | ||||
|                                 FALSE, G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_TOGGLE, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("checked", | ||||
|                                 "Checked", | ||||
|                                 "Indicates if a toggle button is \"on\"" | ||||
|                                 " or \"off\"", | ||||
|                                 FALSE, G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_ACTIVE, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_int ("transition-duration", | ||||
|                             "Transition Duration", | ||||
|                             "Duration of the state transition effect", | ||||
|                             0, G_MAXINT, 120, G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_TRANSITION, pspec); | ||||
|  | ||||
|  | ||||
|   /** | ||||
|    * NbtkButton::clicked: | ||||
|    * @button: the object that received the signal | ||||
|    * | ||||
|    * Emitted when the user activates the button, either with a mouse press and | ||||
|    * release or with the keyboard. | ||||
|    */ | ||||
|  | ||||
|   button_signals[CLICKED] = | ||||
|     g_signal_new ("clicked", | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   G_STRUCT_OFFSET (NbtkButtonClass, clicked), | ||||
|                   NULL, NULL, | ||||
|                   _nbtk_marshal_VOID__VOID, | ||||
|                   G_TYPE_NONE, 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_button_init (NbtkButton *button) | ||||
| { | ||||
|   button->priv = NBTK_BUTTON_GET_PRIVATE (button); | ||||
|   button->priv->transition_duration = 120; | ||||
|   button->priv->spacing = 6; | ||||
|  | ||||
|   clutter_actor_set_reactive ((ClutterActor *) button, TRUE); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_button_new: | ||||
|  * | ||||
|  * Create a new button | ||||
|  * | ||||
|  * Returns: a new #NbtkButton | ||||
|  */ | ||||
| NbtkWidget * | ||||
| nbtk_button_new (void) | ||||
| { | ||||
|   return g_object_new (NBTK_TYPE_BUTTON, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_button_new_with_label: | ||||
|  * @text: text to set the label to | ||||
|  * | ||||
|  * Create a new #NbtkButton with the specified label | ||||
|  * | ||||
|  * Returns: a new #NbtkButton | ||||
|  */ | ||||
| NbtkWidget * | ||||
| nbtk_button_new_with_label (const gchar *text) | ||||
| { | ||||
|   return g_object_new (NBTK_TYPE_BUTTON, "label", text, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_button_get_label: | ||||
|  * @button: a #NbtkButton | ||||
|  * | ||||
|  * Get the text displayed on the button | ||||
|  * | ||||
|  * Returns: the text for the button. This must not be freed by the application | ||||
|  */ | ||||
| G_CONST_RETURN gchar * | ||||
| nbtk_button_get_label (NbtkButton *button) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_BUTTON (button), NULL); | ||||
|  | ||||
|   return button->priv->text; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_button_set_label: | ||||
|  * @button: a #Nbtkbutton | ||||
|  * @text: text to set the label to | ||||
|  * | ||||
|  * Sets the text displayed on the button | ||||
|  */ | ||||
| void | ||||
| nbtk_button_set_label (NbtkButton  *button, | ||||
|                        const gchar *text) | ||||
| { | ||||
|   NbtkButtonPrivate *priv; | ||||
|   ClutterActor *label; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_BUTTON (button)); | ||||
|  | ||||
|   priv = button->priv; | ||||
|  | ||||
|   g_free (priv->text); | ||||
|  | ||||
|   if (text) | ||||
|     priv->text = g_strdup (text); | ||||
|   else | ||||
|     priv->text = g_strdup (""); | ||||
|  | ||||
|   label = nbtk_bin_get_child ((NbtkBin*) button); | ||||
|  | ||||
|   if (label && CLUTTER_IS_TEXT (label)) | ||||
|     { | ||||
|       clutter_text_set_text (CLUTTER_TEXT (label), priv->text); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       label = g_object_new (CLUTTER_TYPE_TEXT, | ||||
|                             "text", priv->text, | ||||
|                             "line-alignment", PANGO_ALIGN_CENTER, | ||||
|                             "ellipsize", PANGO_ELLIPSIZE_END, | ||||
|                             "use-markup", TRUE, | ||||
|                             NULL); | ||||
|       nbtk_bin_set_child ((NbtkBin*) button, label); | ||||
|     } | ||||
|  | ||||
|   /* Fake a style change so that we reset the style properties on the label */ | ||||
|   nbtk_widget_style_changed (NBTK_WIDGET (button)); | ||||
|  | ||||
|   g_object_notify (G_OBJECT (button), "label"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_button_get_toggle_mode: | ||||
|  * @button: a #NbtkButton | ||||
|  * | ||||
|  * Get the toggle mode status of the button. | ||||
|  * | ||||
|  * Returns: #TRUE if toggle mode is set, otherwise #FALSE | ||||
|  */ | ||||
| gboolean | ||||
| nbtk_button_get_toggle_mode (NbtkButton *button) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_BUTTON (button), FALSE); | ||||
|  | ||||
|   return button->priv->is_toggle; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_button_set_toggle_mode: | ||||
|  * @button: a #Nbtkbutton | ||||
|  * @toggle: #TRUE or #FALSE | ||||
|  * | ||||
|  * Enables or disables toggle mode for the button. In toggle mode, the active | ||||
|  * state will be "toggled" when the user clicks the button. | ||||
|  */ | ||||
| void | ||||
| nbtk_button_set_toggle_mode (NbtkButton  *button, | ||||
|                              gboolean     toggle) | ||||
| { | ||||
|   g_return_if_fail (NBTK_IS_BUTTON (button)); | ||||
|  | ||||
|   button->priv->is_toggle = toggle; | ||||
|  | ||||
|   g_object_notify (G_OBJECT (button), "toggle-mode"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_button_get_checked: | ||||
|  * @button: a #NbtkButton | ||||
|  * | ||||
|  * Get the state of the button that is in toggle mode. | ||||
|  * | ||||
|  * Returns: #TRUE if the button is checked, or #FALSE if not | ||||
|  */ | ||||
| gboolean | ||||
| nbtk_button_get_checked (NbtkButton *button) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_BUTTON (button), FALSE); | ||||
|  | ||||
|   return button->priv->is_checked; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_button_set_checked: | ||||
|  * @button: a #Nbtkbutton | ||||
|  * @checked: #TRUE or #FALSE | ||||
|  * | ||||
|  * Sets the pressed state of the button. This is only really useful if the | ||||
|  * button has #toggle-mode mode set to #TRUE. | ||||
|  */ | ||||
| void | ||||
| nbtk_button_set_checked (NbtkButton  *button, | ||||
|                          gboolean     checked) | ||||
| { | ||||
|   g_return_if_fail (NBTK_IS_BUTTON (button)); | ||||
|  | ||||
|   if (button->priv->is_checked != checked) | ||||
|     { | ||||
|       button->priv->is_checked = checked; | ||||
|  | ||||
|       if (checked) | ||||
|         nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "checked"); | ||||
|       else | ||||
|         if (button->priv->is_hover) | ||||
|           nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "hover"); | ||||
|         else | ||||
|           nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, NULL); | ||||
|     } | ||||
|  | ||||
|   g_object_notify (G_OBJECT (button), "checked"); | ||||
| } | ||||
							
								
								
									
										90
									
								
								src/nbtk/nbtk-button.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/nbtk/nbtk-button.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| /* | ||||
|  * nbtk-button.h: Plain button actor | ||||
|  * | ||||
|  * Copyright 2007 OpenedHand | ||||
|  * Copyright 2008, 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: Emmanuele Bassi <ebassi@openedhand.com> | ||||
|  *             Thomas Wood <thomas@linux.intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_BUTTON_H__ | ||||
| #define __NBTK_BUTTON_H__ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #include <nbtk/nbtk-bin.h> | ||||
|  | ||||
| #define NBTK_TYPE_BUTTON                (nbtk_button_get_type ()) | ||||
| #define NBTK_BUTTON(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_BUTTON, NbtkButton)) | ||||
| #define NBTK_IS_BUTTON(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_BUTTON)) | ||||
| #define NBTK_BUTTON_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_BUTTON, NbtkButtonClass)) | ||||
| #define NBTK_IS_BUTTON_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_BUTTON)) | ||||
| #define NBTK_BUTTON_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_BUTTON, NbtkButtonClass)) | ||||
|  | ||||
| typedef struct _NbtkButton              NbtkButton; | ||||
| typedef struct _NbtkButtonPrivate       NbtkButtonPrivate; | ||||
| typedef struct _NbtkButtonClass         NbtkButtonClass; | ||||
|  | ||||
| /** | ||||
|  * NbtkButton: | ||||
|  * | ||||
|  * The contents of this structure is private and should only be accessed using | ||||
|  * the provided API. | ||||
|  */ | ||||
|  | ||||
| struct _NbtkButton | ||||
| { | ||||
|   /*< private >*/ | ||||
|   NbtkBin parent_instance; | ||||
|  | ||||
|   NbtkButtonPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _NbtkButtonClass | ||||
| { | ||||
|   NbtkBinClass parent_class; | ||||
|  | ||||
|   /* vfuncs, not signals */ | ||||
|   void (* pressed)  (NbtkButton *button); | ||||
|   void (* released) (NbtkButton *button); | ||||
|   void (* transition) (NbtkButton *button, ClutterActor *old_bg); | ||||
|  | ||||
|   /* signals */ | ||||
|   void (* clicked) (NbtkButton *button); | ||||
| }; | ||||
|  | ||||
| GType nbtk_button_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| NbtkWidget *          nbtk_button_new            (void); | ||||
| NbtkWidget *          nbtk_button_new_with_label (const gchar  *text); | ||||
| G_CONST_RETURN gchar *nbtk_button_get_label      (NbtkButton   *button); | ||||
| void                  nbtk_button_set_label      (NbtkButton   *button, | ||||
|                                                   const gchar  *text); | ||||
| void                  nbtk_button_set_toggle_mode    (NbtkButton *button, gboolean toggle); | ||||
| gboolean              nbtk_button_get_toggle_mode    (NbtkButton *button); | ||||
| void                  nbtk_button_set_checked        (NbtkButton *button, gboolean checked); | ||||
| gboolean              nbtk_button_get_checked        (NbtkButton *button); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_BUTTON_H__ */ | ||||
							
								
								
									
										367
									
								
								src/nbtk/nbtk-clipboard.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										367
									
								
								src/nbtk/nbtk-clipboard.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,367 @@ | ||||
| /* | ||||
|  * nbtk-clipboard.c: clipboard object | ||||
|  * | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Thomas Wood <thomas.wood@intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include "nbtk-clipboard.h" | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/Xatom.h> | ||||
| #include <clutter/x11/clutter-x11.h> | ||||
| #include <string.h> | ||||
|  | ||||
| G_DEFINE_TYPE (NbtkClipboard, nbtk_clipboard, G_TYPE_OBJECT) | ||||
|  | ||||
| #define CLIPBOARD_PRIVATE(o) \ | ||||
|   (G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_CLIPBOARD, NbtkClipboardPrivate)) | ||||
|  | ||||
| struct _NbtkClipboardPrivate | ||||
| { | ||||
|   Window clipboard_window; | ||||
|   gchar *clipboard_text; | ||||
|  | ||||
|   Atom *supported_targets; | ||||
|   gint n_targets; | ||||
| }; | ||||
|  | ||||
| typedef struct _EventFilterData EventFilterData; | ||||
| struct _EventFilterData | ||||
| { | ||||
|   NbtkClipboard *clipboard; | ||||
|   NbtkClipboardCallbackFunc callback; | ||||
|   gpointer user_data; | ||||
| }; | ||||
|  | ||||
| static Atom __atom_clip = None; | ||||
| static Atom __utf8_string = None; | ||||
| static Atom __atom_targets = None; | ||||
|  | ||||
| static void | ||||
| nbtk_clipboard_get_property (GObject *object, guint property_id, | ||||
|                               GValue *value, GParamSpec *pspec) | ||||
| { | ||||
|   switch (property_id) | ||||
|     { | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_clipboard_set_property (GObject *object, guint property_id, | ||||
|                               const GValue *value, GParamSpec *pspec) | ||||
| { | ||||
|   switch (property_id) | ||||
|     { | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_clipboard_dispose (GObject *object) | ||||
| { | ||||
|   G_OBJECT_CLASS (nbtk_clipboard_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_clipboard_finalize (GObject *object) | ||||
| { | ||||
|   NbtkClipboardPrivate *priv = ((NbtkClipboard *) object)->priv; | ||||
|  | ||||
|   g_free (priv->clipboard_text); | ||||
|   priv->clipboard_text = NULL; | ||||
|  | ||||
|   g_free (priv->supported_targets); | ||||
|   priv->supported_targets = NULL; | ||||
|   priv->n_targets = 0; | ||||
|  | ||||
|   G_OBJECT_CLASS (nbtk_clipboard_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static ClutterX11FilterReturn | ||||
| nbtk_clipboard_provider (XEvent        *xev, | ||||
|                          ClutterEvent  *cev, | ||||
|                          NbtkClipboard *clipboard) | ||||
| { | ||||
|   XSelectionEvent notify_event; | ||||
|   XSelectionRequestEvent *req_event; | ||||
|  | ||||
|   if (xev->type != SelectionRequest) | ||||
|     return CLUTTER_X11_FILTER_CONTINUE; | ||||
|  | ||||
|   req_event = &xev->xselectionrequest; | ||||
|  | ||||
|   clutter_x11_trap_x_errors (); | ||||
|  | ||||
|   if (req_event->target == __atom_targets) | ||||
|     { | ||||
|       XChangeProperty (req_event->display, | ||||
|                        req_event->requestor, | ||||
|                        req_event->property, | ||||
|                        XA_ATOM, | ||||
|                        32, | ||||
|                        PropModeReplace, | ||||
|                        (guchar*) clipboard->priv->supported_targets, | ||||
|                        clipboard->priv->n_targets); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       XChangeProperty (req_event->display, | ||||
|                        req_event->requestor, | ||||
|                        req_event->property, | ||||
|                        req_event->target, | ||||
|                        8, | ||||
|                        PropModeReplace, | ||||
|                        (guchar*) clipboard->priv->clipboard_text, | ||||
|                        strlen (clipboard->priv->clipboard_text)); | ||||
|     } | ||||
|  | ||||
|   notify_event.type = SelectionNotify; | ||||
|   notify_event.display = req_event->display; | ||||
|   notify_event.requestor = req_event->requestor; | ||||
|   notify_event.selection = req_event->selection; | ||||
|   notify_event.target = req_event->target; | ||||
|   notify_event.time = req_event->time; | ||||
|  | ||||
|   if (req_event->property == None) | ||||
|     notify_event.property = req_event->target; | ||||
|   else | ||||
|     notify_event.property = req_event->property; | ||||
|  | ||||
|   /* notify the requestor that they have a copy of the selection */ | ||||
|   XSendEvent (req_event->display, req_event->requestor, False, 0, | ||||
|               (XEvent *) ¬ify_event); | ||||
|   /* Make it happen non async */ | ||||
|   XSync (clutter_x11_get_default_display(), FALSE); | ||||
|  | ||||
|   clutter_x11_untrap_x_errors (); /* FIXME: Warn here on fail ? */ | ||||
|  | ||||
|   return CLUTTER_X11_FILTER_REMOVE; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| nbtk_clipboard_class_init (NbtkClipboardClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (NbtkClipboardPrivate)); | ||||
|  | ||||
|   object_class->get_property = nbtk_clipboard_get_property; | ||||
|   object_class->set_property = nbtk_clipboard_set_property; | ||||
|   object_class->dispose = nbtk_clipboard_dispose; | ||||
|   object_class->finalize = nbtk_clipboard_finalize; | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_clipboard_init (NbtkClipboard *self) | ||||
| { | ||||
|   Display *dpy; | ||||
|   NbtkClipboardPrivate *priv; | ||||
|  | ||||
|   priv = self->priv = CLIPBOARD_PRIVATE (self); | ||||
|  | ||||
|   priv->clipboard_window = | ||||
|     XCreateSimpleWindow (clutter_x11_get_default_display (), | ||||
|                          clutter_x11_get_root_window (), | ||||
|                          -1, -1, 1, 1, 0, 0, 0); | ||||
|  | ||||
|   dpy = clutter_x11_get_default_display (); | ||||
|  | ||||
|   /* Only create once */ | ||||
|   if (__atom_clip == None) | ||||
|     __atom_clip = XInternAtom (dpy, "CLIPBOARD", 0); | ||||
|  | ||||
|   if (__utf8_string == None) | ||||
|     __utf8_string = XInternAtom (dpy, "UTF8_STRING", 0); | ||||
|  | ||||
|   if (__atom_targets == None) | ||||
|     __atom_targets = XInternAtom (dpy, "TARGETS", 0); | ||||
|  | ||||
|   priv->n_targets = 2; | ||||
|   priv->supported_targets = g_new (Atom, priv->n_targets); | ||||
|  | ||||
|   priv->supported_targets[0] = __utf8_string; | ||||
|   priv->supported_targets[1] = __atom_targets; | ||||
|  | ||||
|   clutter_x11_add_filter ((ClutterX11FilterFunc) nbtk_clipboard_provider, | ||||
|                           self); | ||||
| } | ||||
|  | ||||
| static ClutterX11FilterReturn | ||||
| nbtk_clipboard_x11_event_filter (XEvent          *xev, | ||||
|                                  ClutterEvent    *cev, | ||||
|                                  EventFilterData *filter_data) | ||||
| { | ||||
|   Atom actual_type; | ||||
|   int actual_format, result; | ||||
|   unsigned long nitems, bytes_after; | ||||
|   unsigned char *data = NULL; | ||||
|  | ||||
|   if(xev->type != SelectionNotify) | ||||
|     return CLUTTER_X11_FILTER_CONTINUE; | ||||
|  | ||||
|   if (xev->xselection.property == None) | ||||
|     { | ||||
|       /* clipboard empty */ | ||||
|       filter_data->callback (filter_data->clipboard, | ||||
|                              NULL, | ||||
|                              filter_data->user_data); | ||||
|  | ||||
|       clutter_x11_remove_filter ((ClutterX11FilterFunc) nbtk_clipboard_x11_event_filter, | ||||
|                                  filter_data); | ||||
|       g_free (filter_data); | ||||
|       return CLUTTER_X11_FILTER_REMOVE; | ||||
|     } | ||||
|  | ||||
|   clutter_x11_trap_x_errors (); | ||||
|  | ||||
|   result = XGetWindowProperty (xev->xselection.display, | ||||
|                                xev->xselection.requestor, | ||||
|                                xev->xselection.property, | ||||
|                                0L, G_MAXINT, | ||||
|                                True, | ||||
|                                AnyPropertyType, | ||||
|                                &actual_type, | ||||
|                                &actual_format, | ||||
|                                &nitems, | ||||
|                                &bytes_after, | ||||
|                                &data); | ||||
|  | ||||
|   if (clutter_x11_untrap_x_errors () || result != Success) | ||||
|     { | ||||
|       /* FIXME: handle failure better */ | ||||
|       g_warning ("Clipboard: prop retrival failed"); | ||||
|     } | ||||
|  | ||||
|   filter_data->callback (filter_data->clipboard, (char*) data, | ||||
|                          filter_data->user_data); | ||||
|  | ||||
|   clutter_x11_remove_filter | ||||
|                     ((ClutterX11FilterFunc) nbtk_clipboard_x11_event_filter, | ||||
|                      filter_data); | ||||
|  | ||||
|   g_free (filter_data); | ||||
|  | ||||
|   if (data) | ||||
|     XFree (data); | ||||
|  | ||||
|   return CLUTTER_X11_FILTER_REMOVE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_clipboard_get_default: | ||||
|  * | ||||
|  * Get the global #NbtkClipboard object that represents the clipboard. | ||||
|  * | ||||
|  * Returns: (transfer none): a #NbtkClipboard owned by Nbtk and must not be | ||||
|  * unrefferenced or freed. | ||||
|  */ | ||||
| NbtkClipboard* | ||||
| nbtk_clipboard_get_default (void) | ||||
| { | ||||
|   static NbtkClipboard *default_clipboard = NULL; | ||||
|  | ||||
|   if (!default_clipboard) | ||||
|     { | ||||
|       default_clipboard = g_object_new (NBTK_TYPE_CLIPBOARD, NULL); | ||||
|     } | ||||
|  | ||||
|   return default_clipboard; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_clipboard_get_text: | ||||
|  * @clipboard: A #NbtkCliboard | ||||
|  * @callback: function to be called when the text is retreived | ||||
|  * @user_data: data to be passed to the callback | ||||
|  * | ||||
|  * Request the data from the clipboard in text form. @callback is executed | ||||
|  * when the data is retreived. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| nbtk_clipboard_get_text (NbtkClipboard             *clipboard, | ||||
|                          NbtkClipboardCallbackFunc  callback, | ||||
|                          gpointer                   user_data) | ||||
| { | ||||
|   EventFilterData *data; | ||||
|  | ||||
|   Display *dpy; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_CLIPBOARD (clipboard)); | ||||
|   g_return_if_fail (callback != NULL); | ||||
|  | ||||
|   data = g_new0 (EventFilterData, 1); | ||||
|   data->clipboard = clipboard; | ||||
|   data->callback = callback; | ||||
|   data->user_data = user_data; | ||||
|  | ||||
|   clutter_x11_add_filter ((ClutterX11FilterFunc)nbtk_clipboard_x11_event_filter, | ||||
|                           data); | ||||
|  | ||||
|   dpy = clutter_x11_get_default_display (); | ||||
|  | ||||
|   clutter_x11_trap_x_errors (); /* safety on */ | ||||
|  | ||||
|   XConvertSelection (dpy, | ||||
|                      __atom_clip, | ||||
|                      __utf8_string, __utf8_string, | ||||
|                      clipboard->priv->clipboard_window, | ||||
|                      CurrentTime); | ||||
|  | ||||
|   clutter_x11_untrap_x_errors (); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_clipboard_set_text: | ||||
|  * @clipboard: A #NbtkClipboard | ||||
|  * @text: text to copy to the clipboard | ||||
|  * | ||||
|  * Sets text as the current contents of the clipboard. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| nbtk_clipboard_set_text (NbtkClipboard *clipboard, | ||||
|                          const gchar   *text) | ||||
| { | ||||
|   NbtkClipboardPrivate *priv; | ||||
|   Display *dpy; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_CLIPBOARD (clipboard)); | ||||
|   g_return_if_fail (text != NULL); | ||||
|  | ||||
|   priv = clipboard->priv; | ||||
|  | ||||
|   /* make a copy of the text */ | ||||
|   g_free (priv->clipboard_text); | ||||
|   priv->clipboard_text = g_strdup (text); | ||||
|  | ||||
|   /* tell X we own the clipboard selection */ | ||||
|   dpy = clutter_x11_get_default_display (); | ||||
|  | ||||
|   clutter_x11_trap_x_errors (); | ||||
|  | ||||
|   XSetSelectionOwner (dpy, __atom_clip, priv->clipboard_window, CurrentTime); | ||||
|   XSync (dpy, FALSE); | ||||
|  | ||||
|   clutter_x11_untrap_x_errors (); | ||||
| } | ||||
							
								
								
									
										94
									
								
								src/nbtk/nbtk-clipboard.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/nbtk/nbtk-clipboard.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /* | ||||
|  * nbtk-clipboard.h: clipboard object | ||||
|  * | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Thomas Wood <thomas.wood@intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef _NBTK_CLIPBOARD_H | ||||
| #define _NBTK_CLIPBOARD_H | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_CLIPBOARD nbtk_clipboard_get_type() | ||||
|  | ||||
| #define NBTK_CLIPBOARD(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ | ||||
|   NBTK_TYPE_CLIPBOARD, NbtkClipboard)) | ||||
|  | ||||
| #define NBTK_CLIPBOARD_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_CAST ((klass), \ | ||||
|   NBTK_TYPE_CLIPBOARD, NbtkClipboardClass)) | ||||
|  | ||||
| #define NBTK_IS_CLIPBOARD(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ | ||||
|   NBTK_TYPE_CLIPBOARD)) | ||||
|  | ||||
| #define NBTK_IS_CLIPBOARD_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_TYPE ((klass), \ | ||||
|   NBTK_TYPE_CLIPBOARD)) | ||||
|  | ||||
| #define NBTK_CLIPBOARD_GET_CLASS(obj) \ | ||||
|   (G_TYPE_INSTANCE_GET_CLASS ((obj), \ | ||||
|   NBTK_TYPE_CLIPBOARD, NbtkClipboardClass)) | ||||
|  | ||||
| typedef struct _NbtkClipboard NbtkClipboard; | ||||
| typedef struct _NbtkClipboardClass NbtkClipboardClass; | ||||
| typedef struct _NbtkClipboardPrivate NbtkClipboardPrivate; | ||||
|  | ||||
| /** | ||||
|  * NbtkClipboard: | ||||
|  * | ||||
|  * The contents of this structure is private and should only be accessed using | ||||
|  * the provided API. | ||||
|  */ | ||||
| struct _NbtkClipboard | ||||
| { | ||||
|   /*< private >*/ | ||||
|   GObject parent; | ||||
|   NbtkClipboardPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _NbtkClipboardClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * NbtkClipboardCallbackFunc: | ||||
|  * @clipboard: A #NbtkClipboard | ||||
|  * @text: text from the clipboard | ||||
|  * @user_data: user data | ||||
|  * | ||||
|  * Callback function called when text is retrieved from the clipboard. | ||||
|  */ | ||||
| typedef void (*NbtkClipboardCallbackFunc) (NbtkClipboard *clipboard, | ||||
|                                            const gchar   *text, | ||||
|                                            gpointer       user_data); | ||||
|  | ||||
| GType nbtk_clipboard_get_type (void); | ||||
|  | ||||
| NbtkClipboard* nbtk_clipboard_get_default (void); | ||||
| void nbtk_clipboard_get_text (NbtkClipboard *clipboard, NbtkClipboardCallbackFunc callback, gpointer user_data); | ||||
| void nbtk_clipboard_set_text (NbtkClipboard *clipboard, const gchar *text); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* _NBTK_CLIPBOARD_H */ | ||||
							
								
								
									
										897
									
								
								src/nbtk/nbtk-entry.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										897
									
								
								src/nbtk/nbtk-entry.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,897 @@ | ||||
| /* | ||||
|  * nbtk-entry.c: Plain entry actor | ||||
|  * | ||||
|  * Copyright 2008, 2009 Intel Corporation | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Thomas Wood <thomas.wood@intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:nbtk-entry | ||||
|  * @short_description: Widget for displaying text | ||||
|  * | ||||
|  * #NbtkEntry is a simple widget for displaying text. It derives from | ||||
|  * #NbtkWidget to add extra style and placement functionality over | ||||
|  * #ClutterText. The internal #ClutterText is publicly accessibly to allow | ||||
|  * applications to set further properties. | ||||
|  * | ||||
|  * #NbtkEntry supports the following pseudo style states: | ||||
|  * <itemizedlist> | ||||
|  *  <listitem> | ||||
|  *   <para>focus: the widget has focus</para> | ||||
|  *  </listitem> | ||||
|  *  <listitem> | ||||
|  *   <para>indeterminate: the widget is showing the hint text</para> | ||||
|  *  </listitem> | ||||
|  * </itemizedlist> | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <math.h> | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include <glib.h> | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <clutter-imcontext/clutter-imtext.h> | ||||
|  | ||||
| #include "nbtk-entry.h" | ||||
|  | ||||
| #include "nbtk-widget.h" | ||||
| #include "nbtk-texture-cache.h" | ||||
| #include "nbtk-marshal.h" | ||||
| #include "nbtk-clipboard.h" | ||||
|  | ||||
| #define HAS_FOCUS(actor) (clutter_actor_get_stage (actor) && clutter_stage_get_key_focus ((ClutterStage *) clutter_actor_get_stage (actor)) == actor) | ||||
|  | ||||
|  | ||||
| /* properties */ | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_CLUTTER_TEXT, | ||||
|   PROP_HINT_TEXT, | ||||
|   PROP_TEXT, | ||||
| }; | ||||
|  | ||||
| /* signals */ | ||||
| enum | ||||
| { | ||||
|   PRIMARY_ICON_CLICKED, | ||||
|   SECONDARY_ICON_CLICKED, | ||||
|  | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| #define NBTK_ENTRY_GET_PRIVATE(obj)     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_ENTRY, NbtkEntryPrivate)) | ||||
| #define NBTK_ENTRY_PRIV(x) ((NbtkEntry *) x)->priv | ||||
|  | ||||
|  | ||||
| struct _NbtkEntryPrivate | ||||
| { | ||||
|   ClutterActor *entry; | ||||
|   gchar        *hint; | ||||
|  | ||||
|   ClutterActor *primary_icon; | ||||
|   ClutterActor *secondary_icon; | ||||
|  | ||||
|   gfloat   spacing; | ||||
| }; | ||||
|  | ||||
| static guint entry_signals[LAST_SIGNAL] = { 0, }; | ||||
|  | ||||
| G_DEFINE_TYPE (NbtkEntry, nbtk_entry, NBTK_TYPE_WIDGET); | ||||
|  | ||||
| static void | ||||
| nbtk_entry_set_property (GObject      *gobject, | ||||
|                          guint         prop_id, | ||||
|                          const GValue *value, | ||||
|                          GParamSpec   *pspec) | ||||
| { | ||||
|   NbtkEntry *entry = NBTK_ENTRY (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_HINT_TEXT: | ||||
|       nbtk_entry_set_hint_text (entry, g_value_get_string (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TEXT: | ||||
|       nbtk_entry_set_text (entry, g_value_get_string (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_get_property (GObject    *gobject, | ||||
|                          guint       prop_id, | ||||
|                          GValue     *value, | ||||
|                          GParamSpec *pspec) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_CLUTTER_TEXT: | ||||
|       g_value_set_object (value, priv->entry); | ||||
|       break; | ||||
|  | ||||
|     case PROP_HINT_TEXT: | ||||
|       g_value_set_string (value, priv->hint); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TEXT: | ||||
|       g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->entry))); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_dispose (GObject *object) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (object); | ||||
|  | ||||
|   if (priv->entry) | ||||
|     { | ||||
|       clutter_actor_unparent (priv->entry); | ||||
|       priv->entry = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_finalize (GObject *object) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (object); | ||||
|  | ||||
|   g_free (priv->hint); | ||||
|   priv->hint = NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_style_changed (NbtkWidget *self) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (self); | ||||
|   ShellThemeNode *theme_node; | ||||
|   ClutterColor color; | ||||
|   const PangoFontDescription *font; | ||||
|   gchar *font_string; | ||||
|  | ||||
|   theme_node = nbtk_widget_get_theme_node (self); | ||||
|  | ||||
|   shell_theme_node_get_foreground_color (theme_node, &color); | ||||
|   clutter_text_set_color (CLUTTER_TEXT (priv->entry), &color); | ||||
|  | ||||
|   if (shell_theme_node_get_color (theme_node, "caret-color", FALSE, &color)) | ||||
|       clutter_text_set_cursor_color (CLUTTER_TEXT (priv->entry), &color); | ||||
|  | ||||
|   if (shell_theme_node_get_color (theme_node, "selection-background-color", FALSE, &color)) | ||||
|     clutter_text_set_selection_color (CLUTTER_TEXT (priv->entry), &color); | ||||
|  | ||||
|   font = shell_theme_node_get_font (theme_node); | ||||
|   font_string = pango_font_description_to_string (font); | ||||
|   clutter_text_set_font_name (CLUTTER_TEXT (priv->entry), font_string); | ||||
|   g_free (font_string); | ||||
|  | ||||
|   NBTK_WIDGET_CLASS (nbtk_entry_parent_class)->style_changed (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_get_preferred_width (ClutterActor *actor, | ||||
|                                 gfloat   for_height, | ||||
|                                 gfloat  *min_width_p, | ||||
|                                 gfloat  *natural_width_p) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); | ||||
|   gfloat icon_w; | ||||
|  | ||||
|   shell_theme_node_adjust_for_height (theme_node, &for_height); | ||||
|  | ||||
|   clutter_actor_get_preferred_width (priv->entry, for_height, | ||||
|                                      min_width_p, | ||||
|                                      natural_width_p); | ||||
|  | ||||
|   if (priv->primary_icon) | ||||
|     { | ||||
|       clutter_actor_get_preferred_width (priv->primary_icon, -1, NULL, &icon_w); | ||||
|  | ||||
|       if (min_width_p) | ||||
|         *min_width_p += icon_w + priv->spacing; | ||||
|  | ||||
|       if (natural_width_p) | ||||
|         *natural_width_p += icon_w + priv->spacing; | ||||
|     } | ||||
|  | ||||
|   if (priv->secondary_icon) | ||||
|     { | ||||
|       clutter_actor_get_preferred_width (priv->secondary_icon, | ||||
|                                          -1, NULL, &icon_w); | ||||
|  | ||||
|       if (min_width_p) | ||||
|         *min_width_p += icon_w + priv->spacing; | ||||
|  | ||||
|       if (natural_width_p) | ||||
|         *natural_width_p += icon_w + priv->spacing; | ||||
|     } | ||||
|  | ||||
|   shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_get_preferred_height (ClutterActor *actor, | ||||
|                                  gfloat   for_width, | ||||
|                                  gfloat  *min_height_p, | ||||
|                                  gfloat  *natural_height_p) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); | ||||
|   gfloat icon_h; | ||||
|  | ||||
|   shell_theme_node_adjust_for_width (theme_node, &for_width); | ||||
|  | ||||
|   clutter_actor_get_preferred_height (priv->entry, for_width, | ||||
|                                       min_height_p, | ||||
|                                       natural_height_p); | ||||
|  | ||||
|   if (priv->primary_icon) | ||||
|     { | ||||
|       clutter_actor_get_preferred_height (priv->primary_icon, | ||||
|                                           -1, NULL, &icon_h); | ||||
|  | ||||
|       if (min_height_p && icon_h > *min_height_p) | ||||
|         *min_height_p = icon_h; | ||||
|  | ||||
|       if (natural_height_p && icon_h > *natural_height_p) | ||||
|         *natural_height_p = icon_h; | ||||
|     } | ||||
|  | ||||
|   if (priv->secondary_icon) | ||||
|     { | ||||
|       clutter_actor_get_preferred_height (priv->secondary_icon, | ||||
|                                           -1, NULL, &icon_h); | ||||
|  | ||||
|       if (min_height_p && icon_h > *min_height_p) | ||||
|         *min_height_p = icon_h; | ||||
|  | ||||
|       if (natural_height_p && icon_h > *natural_height_p) | ||||
|         *natural_height_p = icon_h; | ||||
|     } | ||||
|  | ||||
|   shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_allocate (ClutterActor          *actor, | ||||
|                      const ClutterActorBox *box, | ||||
|                      ClutterAllocationFlags flags) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); | ||||
|   ClutterActorClass *parent_class; | ||||
|   ClutterActorBox content_box, child_box, icon_box; | ||||
|   gfloat icon_w, icon_h; | ||||
|   gfloat entry_h, min_h, pref_h, avail_h; | ||||
|  | ||||
|   parent_class = CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class); | ||||
|   parent_class->allocate (actor, box, flags); | ||||
|  | ||||
|   shell_theme_node_get_content_box (theme_node, box, &content_box); | ||||
|  | ||||
|   avail_h = content_box.y2 - content_box.y1; | ||||
|  | ||||
|   child_box.x1 = content_box.x1; | ||||
|   child_box.x2 = content_box.x2; | ||||
|  | ||||
|   if (priv->primary_icon) | ||||
|     { | ||||
|       clutter_actor_get_preferred_width (priv->primary_icon, | ||||
|                                          -1, NULL, &icon_w); | ||||
|       clutter_actor_get_preferred_height (priv->primary_icon, | ||||
|                                           -1, NULL, &icon_h); | ||||
|  | ||||
|       icon_box.x1 = content_box.x1; | ||||
|       icon_box.x2 = icon_box.x1 + icon_w; | ||||
|  | ||||
|       icon_box.y1 = (int) (content_box.y1 + avail_h / 2 - icon_h / 2); | ||||
|       icon_box.y2 = icon_box.y1 + icon_h; | ||||
|  | ||||
|       clutter_actor_allocate (priv->primary_icon, | ||||
|                               &icon_box, | ||||
|                               flags); | ||||
|  | ||||
|       /* reduce the size for the entry */ | ||||
|       child_box.x1 += icon_w + priv->spacing; | ||||
|     } | ||||
|  | ||||
|   if (priv->secondary_icon) | ||||
|     { | ||||
|       clutter_actor_get_preferred_width (priv->secondary_icon, | ||||
|                                          -1, NULL, &icon_w); | ||||
|       clutter_actor_get_preferred_height (priv->secondary_icon, | ||||
|                                           -1, NULL, &icon_h); | ||||
|  | ||||
|       icon_box.x2 = content_box.x2; | ||||
|       icon_box.x1 = icon_box.x2 - icon_w; | ||||
|  | ||||
|       icon_box.y1 = (int) (content_box.y1 + avail_h / 2 - icon_h / 2); | ||||
|       icon_box.y2 = icon_box.y1 + icon_h; | ||||
|  | ||||
|       clutter_actor_allocate (priv->secondary_icon, | ||||
|                               &icon_box, | ||||
|                               flags); | ||||
|  | ||||
|       /* reduce the size for the entry */ | ||||
|       child_box.x2 -= icon_w - priv->spacing; | ||||
|     } | ||||
|  | ||||
|   clutter_actor_get_preferred_height (priv->entry, child_box.x2 - child_box.x1, | ||||
|                                       &min_h, &pref_h); | ||||
|  | ||||
|   entry_h = CLAMP (pref_h, min_h, avail_h); | ||||
|  | ||||
|   child_box.y1 = (int) (content_box.y1 + avail_h / 2 - entry_h / 2); | ||||
|   child_box.y2 = child_box.y1 + entry_h; | ||||
|  | ||||
|   clutter_actor_allocate (priv->entry, &child_box, flags); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_text_focus_in_cb (ClutterText *text, | ||||
|                           ClutterActor *actor) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); | ||||
|  | ||||
|   /* remove the hint if visible */ | ||||
|   if (priv->hint | ||||
|       && !strcmp (clutter_text_get_text (text), priv->hint)) | ||||
|     { | ||||
|       clutter_text_set_text (text, ""); | ||||
|     } | ||||
|   nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (actor), "focus"); | ||||
|   clutter_text_set_cursor_visible (text, TRUE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_text_focus_out_cb (ClutterText  *text, | ||||
|                            ClutterActor *actor) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); | ||||
|  | ||||
|   /* add a hint if the entry is empty */ | ||||
|   if (priv->hint && !strcmp (clutter_text_get_text (text), "")) | ||||
|     { | ||||
|       clutter_text_set_text (text, priv->hint); | ||||
|       nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (actor), "indeterminate"); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (actor), NULL); | ||||
|     } | ||||
|   clutter_text_set_cursor_visible (text, FALSE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_paint (ClutterActor *actor) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); | ||||
|   ClutterActorClass *parent_class; | ||||
|  | ||||
|   parent_class = CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class); | ||||
|   parent_class->paint (actor); | ||||
|  | ||||
|   clutter_actor_paint (priv->entry); | ||||
|  | ||||
|   if (priv->primary_icon) | ||||
|     clutter_actor_paint (priv->primary_icon); | ||||
|  | ||||
|   if (priv->secondary_icon) | ||||
|     clutter_actor_paint (priv->secondary_icon); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_pick (ClutterActor *actor, | ||||
|                  const ClutterColor *c) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class)->pick (actor, c); | ||||
|  | ||||
|   clutter_actor_paint (priv->entry); | ||||
|  | ||||
|   if (priv->primary_icon) | ||||
|     clutter_actor_paint (priv->primary_icon); | ||||
|  | ||||
|   if (priv->secondary_icon) | ||||
|     clutter_actor_paint (priv->secondary_icon); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_map (ClutterActor *actor) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY (actor)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class)->map (actor); | ||||
|  | ||||
|   clutter_actor_map (priv->entry); | ||||
|  | ||||
|   if (priv->primary_icon) | ||||
|     clutter_actor_map (priv->primary_icon); | ||||
|  | ||||
|   if (priv->secondary_icon) | ||||
|     clutter_actor_map (priv->secondary_icon); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_unmap (ClutterActor *actor) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY (actor)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class)->unmap (actor); | ||||
|  | ||||
|   clutter_actor_unmap (priv->entry); | ||||
|  | ||||
|   if (priv->primary_icon) | ||||
|     clutter_actor_unmap (priv->primary_icon); | ||||
|  | ||||
|   if (priv->secondary_icon) | ||||
|     clutter_actor_unmap (priv->secondary_icon); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_clipboard_callback (NbtkClipboard *clipboard, | ||||
|                                const gchar   *text, | ||||
|                                gpointer       data) | ||||
| { | ||||
|   ClutterText *ctext = (ClutterText*) ((NbtkEntry *) data)->priv->entry; | ||||
|   gint cursor_pos; | ||||
|  | ||||
|   if (!text) | ||||
|     return; | ||||
|  | ||||
|   /* delete the current selection before pasting */ | ||||
|   clutter_text_delete_selection (ctext); | ||||
|  | ||||
|   /* "paste" the clipboard text into the entry */ | ||||
|   cursor_pos = clutter_text_get_cursor_position (ctext); | ||||
|   clutter_text_insert_text (ctext, text, cursor_pos); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| nbtk_entry_key_press_event (ClutterActor    *actor, | ||||
|                             ClutterKeyEvent *event) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); | ||||
|  | ||||
|   /* This is expected to handle events that were emitted for the inner | ||||
|      ClutterText. They only reach this function if the ClutterText | ||||
|      didn't handle them */ | ||||
|  | ||||
|   /* paste */ | ||||
|   if ((event->modifier_state & CLUTTER_CONTROL_MASK) | ||||
|       && event->keyval == CLUTTER_v) | ||||
|     { | ||||
|       NbtkClipboard *clipboard; | ||||
|  | ||||
|       clipboard = nbtk_clipboard_get_default (); | ||||
|  | ||||
|       nbtk_clipboard_get_text (clipboard, nbtk_entry_clipboard_callback, actor); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   /* copy */ | ||||
|   if ((event->modifier_state & CLUTTER_CONTROL_MASK) | ||||
|       && event->keyval == CLUTTER_c) | ||||
|     { | ||||
|       NbtkClipboard *clipboard; | ||||
|       gchar *text; | ||||
|  | ||||
|       clipboard = nbtk_clipboard_get_default (); | ||||
|  | ||||
|       text = clutter_text_get_selection ((ClutterText*) priv->entry); | ||||
|  | ||||
|       if (text && strlen (text)) | ||||
|         nbtk_clipboard_set_text (clipboard, text); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|  | ||||
|   /* cut */ | ||||
|   if ((event->modifier_state & CLUTTER_CONTROL_MASK) | ||||
|       && event->keyval == CLUTTER_x) | ||||
|     { | ||||
|       NbtkClipboard *clipboard; | ||||
|       gchar *text; | ||||
|  | ||||
|       clipboard = nbtk_clipboard_get_default (); | ||||
|  | ||||
|       text = clutter_text_get_selection ((ClutterText*) priv->entry); | ||||
|  | ||||
|       if (text && strlen (text)) | ||||
|         { | ||||
|           nbtk_clipboard_set_text (clipboard, text); | ||||
|  | ||||
|           /* now delete the text */ | ||||
|           clutter_text_delete_selection ((ClutterText *) priv->entry); | ||||
|         } | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_key_focus_in (ClutterActor *actor) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); | ||||
|  | ||||
|   /* We never want key focus. The ClutterText should be given first | ||||
|      pass for all key events */ | ||||
|   clutter_actor_grab_key_focus (priv->entry); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_class_init (NbtkEntryClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (NbtkEntryPrivate)); | ||||
|  | ||||
|   gobject_class->set_property = nbtk_entry_set_property; | ||||
|   gobject_class->get_property = nbtk_entry_get_property; | ||||
|   gobject_class->finalize = nbtk_entry_finalize; | ||||
|   gobject_class->dispose = nbtk_entry_dispose; | ||||
|  | ||||
|   actor_class->get_preferred_width = nbtk_entry_get_preferred_width; | ||||
|   actor_class->get_preferred_height = nbtk_entry_get_preferred_height; | ||||
|   actor_class->allocate = nbtk_entry_allocate; | ||||
|   actor_class->paint = nbtk_entry_paint; | ||||
|   actor_class->pick = nbtk_entry_pick; | ||||
|   actor_class->map = nbtk_entry_map; | ||||
|   actor_class->unmap = nbtk_entry_unmap; | ||||
|  | ||||
|   actor_class->key_press_event = nbtk_entry_key_press_event; | ||||
|   actor_class->key_focus_in = nbtk_entry_key_focus_in; | ||||
|  | ||||
|   widget_class->style_changed = nbtk_entry_style_changed; | ||||
|  | ||||
|   pspec = g_param_spec_object ("clutter-text", | ||||
| 			       "Clutter Text", | ||||
| 			       "Internal ClutterText actor", | ||||
| 			       CLUTTER_TYPE_TEXT, | ||||
| 			       G_PARAM_READABLE); | ||||
|   g_object_class_install_property (gobject_class, PROP_CLUTTER_TEXT, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_string ("hint-text", | ||||
|                                "Hint Text", | ||||
|                                "Text to display when the entry is not focused " | ||||
|                                "and the text property is empty", | ||||
|                                NULL, G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_HINT_TEXT, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_string ("text", | ||||
|                                "Text", | ||||
|                                "Text of the entry", | ||||
|                                NULL, G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_TEXT, pspec); | ||||
|  | ||||
|   /* signals */ | ||||
|   /** | ||||
|    * NbtkEntry::primary-icon-clicked: | ||||
|    * | ||||
|    * Emitted when the primary icon is clicked | ||||
|    */ | ||||
|   entry_signals[PRIMARY_ICON_CLICKED] = | ||||
|     g_signal_new ("primary-icon-clicked", | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   G_STRUCT_OFFSET (NbtkEntryClass, primary_icon_clicked), | ||||
|                   NULL, NULL, | ||||
|                   _nbtk_marshal_VOID__VOID, | ||||
|                   G_TYPE_NONE, 0); | ||||
|   /** | ||||
|    * NbtkEntry::secondary-icon-clicked: | ||||
|    * | ||||
|    * Emitted when the secondary icon is clicked | ||||
|    */ | ||||
|   entry_signals[SECONDARY_ICON_CLICKED] = | ||||
|     g_signal_new ("secondary-icon-clicked", | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   G_STRUCT_OFFSET (NbtkEntryClass, secondary_icon_clicked), | ||||
|                   NULL, NULL, | ||||
|                   _nbtk_marshal_VOID__VOID, | ||||
|                   G_TYPE_NONE, 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_entry_init (NbtkEntry *entry) | ||||
| { | ||||
|   NbtkEntryPrivate *priv; | ||||
|  | ||||
|   priv = entry->priv = NBTK_ENTRY_GET_PRIVATE (entry); | ||||
|  | ||||
|   priv->entry = g_object_new (CLUTTER_TYPE_IMTEXT, | ||||
|                               "line-alignment", PANGO_ALIGN_LEFT, | ||||
|                               "editable", TRUE, | ||||
|                               "reactive", TRUE, | ||||
|                               "single-line-mode", TRUE, | ||||
|                               NULL); | ||||
|  | ||||
|   g_signal_connect (priv->entry, "key-focus-in", | ||||
|                     G_CALLBACK (clutter_text_focus_in_cb), entry); | ||||
|  | ||||
|   g_signal_connect (priv->entry, "key-focus-out", | ||||
|                     G_CALLBACK (clutter_text_focus_out_cb), entry); | ||||
|  | ||||
|   priv->spacing = 6.0f; | ||||
|  | ||||
|   clutter_actor_set_parent (priv->entry, CLUTTER_ACTOR (entry)); | ||||
|   clutter_actor_set_reactive ((ClutterActor *) entry, TRUE); | ||||
|  | ||||
|   /* set cursor hidden until we receive focus */ | ||||
|   clutter_text_set_cursor_visible ((ClutterText *) priv->entry, FALSE); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_entry_new: | ||||
|  * @text: text to set the entry to | ||||
|  * | ||||
|  * Create a new #NbtkEntry with the specified entry | ||||
|  * | ||||
|  * Returns: a new #NbtkEntry | ||||
|  */ | ||||
| NbtkWidget * | ||||
| nbtk_entry_new (const gchar *text) | ||||
| { | ||||
|   NbtkWidget *entry; | ||||
|  | ||||
|   /* add the entry to the stage, but don't allow it to be visible */ | ||||
|   entry = g_object_new (NBTK_TYPE_ENTRY, | ||||
|                         "text", text, | ||||
|                         NULL); | ||||
|  | ||||
|   return entry; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_entry_get_text: | ||||
|  * @entry: a #NbtkEntry | ||||
|  * | ||||
|  * Get the text displayed on the entry | ||||
|  * | ||||
|  * Returns: the text for the entry. This must not be freed by the application | ||||
|  */ | ||||
| G_CONST_RETURN gchar * | ||||
| nbtk_entry_get_text (NbtkEntry *entry) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_ENTRY (entry), NULL); | ||||
|  | ||||
|   return clutter_text_get_text (CLUTTER_TEXT (entry->priv->entry)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_entry_set_text: | ||||
|  * @entry: a #NbtkEntry | ||||
|  * @text: text to set the entry to | ||||
|  * | ||||
|  * Sets the text displayed on the entry | ||||
|  */ | ||||
| void | ||||
| nbtk_entry_set_text (NbtkEntry *entry, | ||||
|                      const gchar *text) | ||||
| { | ||||
|   NbtkEntryPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_ENTRY (entry)); | ||||
|  | ||||
|   priv = entry->priv; | ||||
|  | ||||
|   /* set a hint if we are blanking the entry */ | ||||
|   if (priv->hint | ||||
|       && text && !strcmp ("", text) | ||||
|       && !HAS_FOCUS (priv->entry)) | ||||
|     { | ||||
|       text = priv->hint; | ||||
|       nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), "indeterminate"); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (HAS_FOCUS (priv->entry)) | ||||
|         nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), "focus"); | ||||
|       else | ||||
|         nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), NULL); | ||||
|     } | ||||
|  | ||||
|   clutter_text_set_text (CLUTTER_TEXT (priv->entry), text); | ||||
|  | ||||
|   g_object_notify (G_OBJECT (entry), "text"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_entry_get_clutter_text: | ||||
|  * @entry: a #NbtkEntry | ||||
|  * | ||||
|  * Retrieve the internal #ClutterText so that extra parameters can be set | ||||
|  * | ||||
|  * Returns: (transfer none): the #ClutterText used by #NbtkEntry. The entry is | ||||
|  * owned by the #NbtkEntry and should not be unref'ed by the application. | ||||
|  */ | ||||
| ClutterActor* | ||||
| nbtk_entry_get_clutter_text (NbtkEntry *entry) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_ENTRY (entry), NULL); | ||||
|  | ||||
|   return entry->priv->entry; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_entry_set_hint_text: | ||||
|  * @entry: a #NbtkEntry | ||||
|  * @text: text to set as the entry hint | ||||
|  * | ||||
|  * Sets the text to display when the entry is empty and unfocused. When the | ||||
|  * entry is displaying the hint, it has a pseudo class of "indeterminate". | ||||
|  * A value of NULL unsets the hint. | ||||
|  */ | ||||
| void | ||||
| nbtk_entry_set_hint_text (NbtkEntry *entry, | ||||
|                           const gchar *text) | ||||
| { | ||||
|   NbtkEntryPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_ENTRY (entry)); | ||||
|  | ||||
|   priv = entry->priv; | ||||
|  | ||||
|   g_free (priv->hint); | ||||
|  | ||||
|   priv->hint = g_strdup (text); | ||||
|  | ||||
|   if (!strcmp (clutter_text_get_text (CLUTTER_TEXT (priv->entry)), "")) | ||||
|     { | ||||
|       clutter_text_set_text (CLUTTER_TEXT (priv->entry), priv->hint); | ||||
|       nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), "indeterminate"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_entry_get_hint_text: | ||||
|  * @entry: a #NbtkEntry | ||||
|  * | ||||
|  * Gets the text that is displayed when the entry is empty and unfocused | ||||
|  * | ||||
|  * Returns: the current value of the hint property. This string is owned by the | ||||
|  * #NbtkEntry and should not be freed or modified. | ||||
|  */ | ||||
| G_CONST_RETURN | ||||
| gchar * | ||||
| nbtk_entry_get_hint_text (NbtkEntry *entry) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_ENTRY (entry), NULL); | ||||
|  | ||||
|   return entry->priv->hint; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| _nbtk_entry_icon_press_cb (ClutterActor       *actor, | ||||
|                            ClutterButtonEvent *event, | ||||
|                            NbtkEntry          *entry) | ||||
| { | ||||
|   NbtkEntryPrivate *priv = entry->priv; | ||||
|  | ||||
|   if (actor == priv->primary_icon) | ||||
|     g_signal_emit (entry, entry_signals[PRIMARY_ICON_CLICKED], 0); | ||||
|   else | ||||
|     g_signal_emit (entry, entry_signals[SECONDARY_ICON_CLICKED], 0); | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| _nbtk_entry_set_icon_from_file (NbtkEntry     *entry, | ||||
|                                 ClutterActor **icon, | ||||
|                                 const gchar   *filename) | ||||
| { | ||||
|   if (*icon) | ||||
|     { | ||||
|       g_signal_handlers_disconnect_by_func (*icon, | ||||
|                                             _nbtk_entry_icon_press_cb, | ||||
|                                             entry); | ||||
|       clutter_actor_unparent (*icon); | ||||
|       *icon = NULL; | ||||
|     } | ||||
|  | ||||
|   if (filename) | ||||
|     { | ||||
|       NbtkTextureCache *cache; | ||||
|  | ||||
|       cache = nbtk_texture_cache_get_default (); | ||||
|  | ||||
|  | ||||
|  | ||||
|       *icon = (ClutterActor*) nbtk_texture_cache_get_texture (cache, filename, FALSE); | ||||
|  | ||||
|       clutter_actor_set_reactive (*icon, TRUE); | ||||
|       clutter_actor_set_parent (*icon, CLUTTER_ACTOR (entry)); | ||||
|       g_signal_connect (*icon, "button-release-event", | ||||
|                         G_CALLBACK (_nbtk_entry_icon_press_cb), entry); | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_relayout (CLUTTER_ACTOR (entry)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_entry_set_primary_icon_from_file: | ||||
|  * @entry: a #NbtkEntry | ||||
|  * @filename: filename of an icon | ||||
|  * | ||||
|  * Set the primary icon of the entry to the given filename | ||||
|  */ | ||||
| void | ||||
| nbtk_entry_set_primary_icon_from_file (NbtkEntry   *entry, | ||||
|                                        const gchar *filename) | ||||
| { | ||||
|   NbtkEntryPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_ENTRY (entry)); | ||||
|  | ||||
|   priv = entry->priv; | ||||
|  | ||||
|   _nbtk_entry_set_icon_from_file (entry, &priv->primary_icon, filename); | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_entry_set_secondary_icon_from_file: | ||||
|  * @entry: a #NbtkEntry | ||||
|  * @filename: filename of an icon | ||||
|  * | ||||
|  * Set the primary icon of the entry to the given filename | ||||
|  */ | ||||
| void | ||||
| nbtk_entry_set_secondary_icon_from_file (NbtkEntry   *entry, | ||||
|                                          const gchar *filename) | ||||
| { | ||||
|   NbtkEntryPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_ENTRY (entry)); | ||||
|  | ||||
|   priv = entry->priv; | ||||
|  | ||||
|   _nbtk_entry_set_icon_from_file (entry, &priv->secondary_icon, filename); | ||||
|  | ||||
| } | ||||
							
								
								
									
										88
									
								
								src/nbtk/nbtk-entry.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/nbtk/nbtk-entry.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| /* | ||||
|  * nbtk-entry.h: Plain entry actor | ||||
|  * | ||||
|  * Copyright 2008, 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: Thomas Wood <thomas@linux.intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_ENTRY_H__ | ||||
| #define __NBTK_ENTRY_H__ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #include <nbtk/nbtk-widget.h> | ||||
|  | ||||
| #define NBTK_TYPE_ENTRY                (nbtk_entry_get_type ()) | ||||
| #define NBTK_ENTRY(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_ENTRY, NbtkEntry)) | ||||
| #define NBTK_IS_ENTRY(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_ENTRY)) | ||||
| #define NBTK_ENTRY_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_ENTRY, NbtkEntryClass)) | ||||
| #define NBTK_IS_ENTRY_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_ENTRY)) | ||||
| #define NBTK_ENTRY_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_ENTRY, NbtkEntryClass)) | ||||
|  | ||||
| typedef struct _NbtkEntry              NbtkEntry; | ||||
| typedef struct _NbtkEntryPrivate       NbtkEntryPrivate; | ||||
| typedef struct _NbtkEntryClass         NbtkEntryClass; | ||||
|  | ||||
| /** | ||||
|  * NbtkEntry: | ||||
|  * | ||||
|  * The contents of this structure is private and should only be accessed using | ||||
|  * the provided API. | ||||
|  */ | ||||
| struct _NbtkEntry | ||||
| { | ||||
|   /*< private >*/ | ||||
|   NbtkWidget parent_instance; | ||||
|  | ||||
|   NbtkEntryPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _NbtkEntryClass | ||||
| { | ||||
|   NbtkWidgetClass parent_class; | ||||
|  | ||||
|   /* signals */ | ||||
|   void (*primary_icon_clicked) (NbtkEntry *entry); | ||||
|   void (*secondary_icon_clicked) (NbtkEntry *entry); | ||||
| }; | ||||
|  | ||||
| GType nbtk_entry_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| NbtkWidget *          nbtk_entry_new              (const gchar *text); | ||||
| G_CONST_RETURN gchar *nbtk_entry_get_text         (NbtkEntry   *entry); | ||||
| void                  nbtk_entry_set_text         (NbtkEntry   *entry, | ||||
|                                                    const gchar *text); | ||||
| ClutterActor*         nbtk_entry_get_clutter_text (NbtkEntry   *entry); | ||||
|  | ||||
| void                  nbtk_entry_set_hint_text (NbtkEntry *entry, | ||||
|                                                 const gchar *text); | ||||
| G_CONST_RETURN gchar *nbtk_entry_get_hint_text (NbtkEntry *entry); | ||||
|  | ||||
| void nbtk_entry_set_primary_icon_from_file (NbtkEntry   *entry, | ||||
|                                             const gchar *filename); | ||||
| void nbtk_entry_set_secondary_icon_from_file (NbtkEntry   *entry, | ||||
|                                               const gchar *filename); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_ENTRY_H__ */ | ||||
							
								
								
									
										30
									
								
								src/nbtk/nbtk-enum-types.c.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/nbtk/nbtk-enum-types.c.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| /*** BEGIN file-header ***/ | ||||
| #include "nbtk-enum-types.h" | ||||
| /*** END file-header ***/ | ||||
|  | ||||
| /*** BEGIN file-production ***/ | ||||
| /* enumerations from "@filename@" */ | ||||
| #include "@filename@" | ||||
| /*** END file-production ***/ | ||||
|  | ||||
| /*** BEGIN value-header ***/ | ||||
| GType | ||||
| @enum_name@_get_type(void) { | ||||
|   static GType enum_type_id = 0; | ||||
|   if (G_UNLIKELY (!enum_type_id)) | ||||
|     { | ||||
|       static const G@Type@Value values[] = { | ||||
| /*** END value-header ***/ | ||||
|  | ||||
| /*** BEGIN value-production ***/ | ||||
|         { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, | ||||
| /*** END value-production ***/ | ||||
|  | ||||
| /*** BEGIN value-tail ***/ | ||||
|         { 0, NULL, NULL } | ||||
|       }; | ||||
|       enum_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); | ||||
|     } | ||||
|   return enum_type_id; | ||||
| } | ||||
| /*** END value-tail ***/ | ||||
							
								
								
									
										29
									
								
								src/nbtk/nbtk-enum-types.h.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/nbtk/nbtk-enum-types.h.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| /*** BEGIN file-header ***/ | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_ENUM_TYPES_H__ | ||||
| #define __NBTK_ENUM_TYPES_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| /*** END file-header ***/ | ||||
|  | ||||
| /*** BEGIN file-production ***/ | ||||
| /* enumerations from "@filename@" */ | ||||
| /*** END file-production ***/ | ||||
|  | ||||
| /*** BEGIN file-tail ***/ | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* !__NBTK_ENUM_TYPES_H__ */ | ||||
| /*** END file-tail ***/ | ||||
|  | ||||
| /*** BEGIN value-header ***/ | ||||
| GType @enum_name@_get_type (void) G_GNUC_CONST; | ||||
| #define NBTK_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) | ||||
|  | ||||
| /*** END value-header ***/ | ||||
							
								
								
									
										341
									
								
								src/nbtk/nbtk-label.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										341
									
								
								src/nbtk/nbtk-label.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,341 @@ | ||||
| /* | ||||
|  * nbtk-label.c: Plain label actor | ||||
|  * | ||||
|  * Copyright 2008,2009 Intel Corporation | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Thomas Wood <thomas@linux.intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:nbtk-label | ||||
|  * @short_description: Widget for displaying text | ||||
|  * | ||||
|  * #NbtkLabel is a simple widget for displaying text. It derives from | ||||
|  * #NbtkWidget to add extra style and placement functionality over | ||||
|  * #ClutterText. The internal #ClutterText is publicly accessibly to allow | ||||
|  * applications to set further properties. | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include <glib.h> | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "nbtk-label.h" | ||||
|  | ||||
| #include "nbtk-widget.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_CLUTTER_TEXT, | ||||
|   PROP_TEXT | ||||
| }; | ||||
|  | ||||
| #define NBTK_LABEL_GET_PRIVATE(obj)     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_LABEL, NbtkLabelPrivate)) | ||||
|  | ||||
| struct _NbtkLabelPrivate | ||||
| { | ||||
|   ClutterActor *label; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (NbtkLabel, nbtk_label, NBTK_TYPE_WIDGET); | ||||
|  | ||||
| static void | ||||
| nbtk_label_set_property (GObject      *gobject, | ||||
|                            guint         prop_id, | ||||
|                            const GValue *value, | ||||
|                            GParamSpec   *pspec) | ||||
| { | ||||
|   NbtkLabel *label = NBTK_LABEL (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_TEXT: | ||||
|       nbtk_label_set_text (label, g_value_get_string (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_label_get_property (GObject    *gobject, | ||||
|                            guint       prop_id, | ||||
|                            GValue     *value, | ||||
|                            GParamSpec *pspec) | ||||
| { | ||||
|   NbtkLabelPrivate *priv = NBTK_LABEL (gobject)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_CLUTTER_TEXT: | ||||
|       g_value_set_object (value, priv->label); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TEXT: | ||||
|       g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->label))); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_label_style_changed (NbtkWidget *self) | ||||
| { | ||||
|   NbtkLabelPrivate *priv; | ||||
|   ShellThemeNode *theme_node; | ||||
|   ClutterColor color; | ||||
|   const PangoFontDescription *font; | ||||
|   gchar *font_string; | ||||
|  | ||||
|   priv = NBTK_LABEL (self)->priv; | ||||
|   theme_node = nbtk_widget_get_theme_node (self); | ||||
|   shell_theme_node_get_foreground_color (theme_node, &color); | ||||
|   clutter_text_set_color (CLUTTER_TEXT (priv->label), &color); | ||||
|  | ||||
|   font = shell_theme_node_get_font (theme_node); | ||||
|   font_string = pango_font_description_to_string (font); | ||||
|   clutter_text_set_font_name (CLUTTER_TEXT (priv->label), font_string); | ||||
|   g_free (font_string); | ||||
|  | ||||
|   NBTK_WIDGET_CLASS (nbtk_label_parent_class)->style_changed (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_label_get_preferred_width (ClutterActor *actor, | ||||
|                                 gfloat        for_height, | ||||
|                                 gfloat       *min_width_p, | ||||
|                                 gfloat       *natural_width_p) | ||||
| { | ||||
|   NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv; | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); | ||||
|  | ||||
|   shell_theme_node_adjust_for_height (theme_node, &for_height); | ||||
|  | ||||
|   clutter_actor_get_preferred_width (priv->label, for_height, | ||||
|                                      min_width_p, | ||||
|                                      natural_width_p); | ||||
|  | ||||
|   shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_label_get_preferred_height (ClutterActor *actor, | ||||
|                                  gfloat        for_width, | ||||
|                                  gfloat       *min_height_p, | ||||
|                                  gfloat       *natural_height_p) | ||||
| { | ||||
|   NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv; | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); | ||||
|  | ||||
|   shell_theme_node_adjust_for_width (theme_node, &for_width); | ||||
|  | ||||
|   clutter_actor_get_preferred_height (priv->label, for_width, | ||||
|                                       min_height_p, | ||||
|                                       natural_height_p); | ||||
|  | ||||
|   shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_label_allocate (ClutterActor          *actor, | ||||
|                      const ClutterActorBox *box, | ||||
|                      ClutterAllocationFlags flags) | ||||
| { | ||||
|   NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv; | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); | ||||
|   ClutterActorClass *parent_class; | ||||
|   ClutterActorBox content_box; | ||||
|  | ||||
|   shell_theme_node_get_content_box (theme_node, box, &content_box); | ||||
|  | ||||
|   parent_class = CLUTTER_ACTOR_CLASS (nbtk_label_parent_class); | ||||
|   parent_class->allocate (actor, box, flags); | ||||
|  | ||||
|   clutter_actor_allocate (priv->label, &content_box, flags); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_label_paint (ClutterActor *actor) | ||||
| { | ||||
|   NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv; | ||||
|   ClutterActorClass *parent_class; | ||||
|  | ||||
|   parent_class = CLUTTER_ACTOR_CLASS (nbtk_label_parent_class); | ||||
|   parent_class->paint (actor); | ||||
|  | ||||
|   clutter_actor_paint (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_label_map (ClutterActor *actor) | ||||
| { | ||||
|   NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_label_parent_class)->map (actor); | ||||
|  | ||||
|   clutter_actor_map (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_label_unmap (ClutterActor *actor) | ||||
| { | ||||
|   NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_label_parent_class)->unmap (actor); | ||||
|  | ||||
|   clutter_actor_unmap (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_label_class_init (NbtkLabelClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (NbtkLabelPrivate)); | ||||
|  | ||||
|   gobject_class->set_property = nbtk_label_set_property; | ||||
|   gobject_class->get_property = nbtk_label_get_property; | ||||
|  | ||||
|   actor_class->paint = nbtk_label_paint; | ||||
|   actor_class->allocate = nbtk_label_allocate; | ||||
|   actor_class->get_preferred_width = nbtk_label_get_preferred_width; | ||||
|   actor_class->get_preferred_height = nbtk_label_get_preferred_height; | ||||
|   actor_class->map = nbtk_label_map; | ||||
|   actor_class->unmap = nbtk_label_unmap; | ||||
|  | ||||
|   widget_class->style_changed = nbtk_label_style_changed; | ||||
|  | ||||
|   pspec = g_param_spec_object ("clutter-text", | ||||
| 			       "Clutter Text", | ||||
| 			       "Internal ClutterText actor", | ||||
| 			       CLUTTER_TYPE_TEXT, | ||||
| 			       G_PARAM_READABLE); | ||||
|   g_object_class_install_property (gobject_class, PROP_CLUTTER_TEXT, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_string ("text", | ||||
|                                "Text", | ||||
|                                "Text of the label", | ||||
|                                NULL, G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_TEXT, pspec); | ||||
|  | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_label_init (NbtkLabel *label) | ||||
| { | ||||
|   NbtkLabelPrivate *priv; | ||||
|  | ||||
|   label->priv = priv = NBTK_LABEL_GET_PRIVATE (label); | ||||
|  | ||||
|   label->priv->label = g_object_new (CLUTTER_TYPE_TEXT, | ||||
|                                      "ellipsize", PANGO_ELLIPSIZE_END, | ||||
|                                      NULL); | ||||
|  | ||||
|   clutter_actor_set_parent (priv->label, CLUTTER_ACTOR (label)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_label_new: | ||||
|  * @text: text to set the label to | ||||
|  * | ||||
|  * Create a new #NbtkLabel with the specified label | ||||
|  * | ||||
|  * Returns: a new #NbtkLabel | ||||
|  */ | ||||
| NbtkWidget * | ||||
| nbtk_label_new (const gchar *text) | ||||
| { | ||||
|   if (text == NULL || *text == '\0') | ||||
|     return g_object_new (NBTK_TYPE_LABEL, NULL); | ||||
|   else | ||||
|     return g_object_new (NBTK_TYPE_LABEL, | ||||
|                          "text", text, | ||||
|                          NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_label_get_text: | ||||
|  * @label: a #NbtkLabel | ||||
|  * | ||||
|  * Get the text displayed on the label | ||||
|  * | ||||
|  * Returns: the text for the label. This must not be freed by the application | ||||
|  */ | ||||
| G_CONST_RETURN gchar * | ||||
| nbtk_label_get_text (NbtkLabel *label) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_LABEL (label), NULL); | ||||
|  | ||||
|   return clutter_text_get_text (CLUTTER_TEXT (label->priv->label)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_label_set_text: | ||||
|  * @label: a #NbtkLabel | ||||
|  * @text: text to set the label to | ||||
|  * | ||||
|  * Sets the text displayed on the label | ||||
|  */ | ||||
| void | ||||
| nbtk_label_set_text (NbtkLabel *label, | ||||
|                      const gchar *text) | ||||
| { | ||||
|   NbtkLabelPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_LABEL (label)); | ||||
|   g_return_if_fail (text != NULL); | ||||
|  | ||||
|   priv = label->priv; | ||||
|  | ||||
|   clutter_text_set_text (CLUTTER_TEXT (priv->label), text); | ||||
|  | ||||
|   g_object_notify (G_OBJECT (label), "text"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_label_get_clutter_text: | ||||
|  * @label: a #NbtkLabel | ||||
|  * | ||||
|  * Retrieve the internal #ClutterText so that extra parameters can be set | ||||
|  * | ||||
|  * Returns: (transfer none): ethe #ClutterText used by #NbtkLabel. The label | ||||
|  * is owned by the #NbtkLabel and should not be unref'ed by the application. | ||||
|  */ | ||||
| ClutterActor* | ||||
| nbtk_label_get_clutter_text (NbtkLabel *label) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_LABEL (label), NULL); | ||||
|  | ||||
|   return label->priv->label; | ||||
| } | ||||
							
								
								
									
										75
									
								
								src/nbtk/nbtk-label.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/nbtk/nbtk-label.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| /* | ||||
|  * nbtk-label.h: Plain label actor | ||||
|  * | ||||
|  * Copyright 2008, 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: Thomas Wood <thomas@linux.intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_LABEL_H__ | ||||
| #define __NBTK_LABEL_H__ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #include <nbtk/nbtk-widget.h> | ||||
|  | ||||
| #define NBTK_TYPE_LABEL                (nbtk_label_get_type ()) | ||||
| #define NBTK_LABEL(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_LABEL, NbtkLabel)) | ||||
| #define NBTK_IS_LABEL(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_LABEL)) | ||||
| #define NBTK_LABEL_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_LABEL, NbtkLabelClass)) | ||||
| #define NBTK_IS_LABEL_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_LABEL)) | ||||
| #define NBTK_LABEL_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_LABEL, NbtkLabelClass)) | ||||
|  | ||||
| typedef struct _NbtkLabel              NbtkLabel; | ||||
| typedef struct _NbtkLabelPrivate       NbtkLabelPrivate; | ||||
| typedef struct _NbtkLabelClass         NbtkLabelClass; | ||||
|  | ||||
| /** | ||||
|  * NbtkLabel: | ||||
|  * | ||||
|  * The contents of this structure is private and should only be accessed using | ||||
|  * the provided API. | ||||
|  */ | ||||
| struct _NbtkLabel | ||||
| { | ||||
|   /*< private >*/ | ||||
|   NbtkWidget parent_instance; | ||||
|  | ||||
|   NbtkLabelPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _NbtkLabelClass | ||||
| { | ||||
|   NbtkWidgetClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType nbtk_label_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| NbtkWidget *          nbtk_label_new              (const gchar *text); | ||||
| G_CONST_RETURN gchar *nbtk_label_get_text         (NbtkLabel   *label); | ||||
| void                  nbtk_label_set_text         (NbtkLabel   *label, | ||||
|                                                    const gchar *text); | ||||
| ClutterActor *        nbtk_label_get_clutter_text (NbtkLabel   *label); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_LABEL_H__ */ | ||||
							
								
								
									
										12
									
								
								src/nbtk/nbtk-marshal.list
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/nbtk/nbtk-marshal.list
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| VOID:OBJECT | ||||
| VOID:VOID | ||||
| VOID:PARAM | ||||
| VOID:POINTER | ||||
| VOID:UINT | ||||
| VOID:UINT,UINT | ||||
| VOID:OBJECT,OBJECT | ||||
| VOID:STRING,OBJECT | ||||
| VOID:OBJECT,OBJECT,INT,INT | ||||
| VOID:OBJECT,FLOAT,FLOAT,INT,ENUM | ||||
| VOID:FLOAT,FLOAT,INT,ENUM | ||||
| VOID:FLOAT,FLOAT | ||||
							
								
								
									
										111
									
								
								src/nbtk/nbtk-private.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								src/nbtk/nbtk-private.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| #include "nbtk-private.h" | ||||
|  | ||||
| /* Utility function to modify a child allocation box with respect to the | ||||
|  * x/y-fill child properties. Expects childbox to contain the available | ||||
|  * allocation space. | ||||
|  */ | ||||
| void | ||||
| _nbtk_allocate_fill (ClutterActor *child, | ||||
|                      ClutterActorBox *childbox, | ||||
|                      NbtkAlign x_alignment, | ||||
|                      NbtkAlign y_alignment, | ||||
|                      gboolean x_fill, | ||||
|                      gboolean y_fill) | ||||
| { | ||||
|   gfloat natural_width, natural_height; | ||||
|   gfloat min_width, min_height; | ||||
|   gfloat child_width, child_height; | ||||
|   gfloat available_width, available_height; | ||||
|   ClutterRequestMode request; | ||||
|   ClutterActorBox allocation = { 0, }; | ||||
|   gdouble x_align, y_align; | ||||
|  | ||||
|   if (x_alignment == NBTK_ALIGN_START) | ||||
|     x_align = 0.0; | ||||
|   else if (x_alignment == NBTK_ALIGN_MIDDLE) | ||||
|     x_align = 0.5; | ||||
|   else | ||||
|     x_align = 1.0; | ||||
|  | ||||
|   if (y_alignment == NBTK_ALIGN_START) | ||||
|     y_align = 0.0; | ||||
|   else if (y_alignment == NBTK_ALIGN_MIDDLE) | ||||
|     y_align = 0.5; | ||||
|   else | ||||
|     y_align = 1.0; | ||||
|  | ||||
|   available_width  = childbox->x2 - childbox->x1; | ||||
|   available_height = childbox->y2 - childbox->y1; | ||||
|  | ||||
|   if (available_width < 0) | ||||
|     available_width = 0; | ||||
|  | ||||
|   if (available_height < 0) | ||||
|     available_height = 0; | ||||
|  | ||||
|   if (x_fill) | ||||
|     { | ||||
|       allocation.x1 = childbox->x1; | ||||
|       allocation.x2 = (int) (allocation.x1 + available_width); | ||||
|     } | ||||
|  | ||||
|   if (y_fill) | ||||
|     { | ||||
|       allocation.y1 = childbox->y1; | ||||
|       allocation.y2 = (int) (allocation.y1 + available_height); | ||||
|     } | ||||
|  | ||||
|   /* if we are filling horizontally and vertically then we're done */ | ||||
|   if (x_fill && y_fill) | ||||
|     { | ||||
|       *childbox = allocation; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH; | ||||
|   g_object_get (G_OBJECT (child), "request-mode", &request, NULL); | ||||
|  | ||||
|   if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) | ||||
|     { | ||||
|       clutter_actor_get_preferred_width (child, available_height, | ||||
|                                          &min_width, | ||||
|                                          &natural_width); | ||||
|  | ||||
|       child_width = CLAMP (natural_width, min_width, available_width); | ||||
|  | ||||
|       clutter_actor_get_preferred_height (child, child_width, | ||||
|                                           &min_height, | ||||
|                                           &natural_height); | ||||
|  | ||||
|       child_height = CLAMP (natural_height, min_height, available_height); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       clutter_actor_get_preferred_height (child, available_width, | ||||
|                                           &min_height, | ||||
|                                           &natural_height); | ||||
|  | ||||
|       child_height = CLAMP (natural_height, min_height, available_height); | ||||
|  | ||||
|       clutter_actor_get_preferred_width (child, child_height, | ||||
|                                          &min_width, | ||||
|                                          &natural_width); | ||||
|  | ||||
|       child_width = CLAMP (natural_width, min_width, available_width); | ||||
|     } | ||||
|  | ||||
|   if (!x_fill) | ||||
|     { | ||||
|       allocation.x1 = childbox->x1 + (int) ((available_width - child_width) * x_align); | ||||
|       allocation.x2 = allocation.x1 + (int) child_width; | ||||
|     } | ||||
|  | ||||
|   if (!y_fill) | ||||
|     { | ||||
|       allocation.y1 = childbox->y1 + (int) ((available_height - child_height) * y_align); | ||||
|       allocation.y2 = allocation.y1 + (int) child_height; | ||||
|     } | ||||
|  | ||||
|   *childbox = allocation; | ||||
|  | ||||
| } | ||||
							
								
								
									
										49
									
								
								src/nbtk/nbtk-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/nbtk/nbtk-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| /* | ||||
|  * nbtk-private.h: Private declarations | ||||
|  * | ||||
|  * Copyright 2007 OpenedHand | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef __NBTK_PRIVATE_H__ | ||||
| #define __NBTK_PRIVATE_H__ | ||||
|  | ||||
| #include <glib.h> | ||||
| #include "nbtk-widget.h" | ||||
| #include "nbtk-bin.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define I_(str)         (g_intern_static_string ((str))) | ||||
|  | ||||
| #define NBTK_PARAM_READABLE     \ | ||||
|         (G_PARAM_READABLE |     \ | ||||
|          G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB) | ||||
|  | ||||
| #define NBTK_PARAM_READWRITE    \ | ||||
|         (G_PARAM_READABLE | G_PARAM_WRITABLE | \ | ||||
|          G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB) | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| ClutterActor *_nbtk_widget_get_dnd_clone (NbtkWidget *widget); | ||||
| void _nbtk_bin_get_align_factors (NbtkBin *bin, gdouble *x_align, gdouble *y_align); | ||||
|  | ||||
| void _nbtk_allocate_fill (ClutterActor *child, ClutterActorBox *childbox, NbtkAlign x_align, NbtkAlign y_align, gboolean x_fill, gboolean y_fill); | ||||
|  | ||||
| #endif /* __NBTK_PRIVATE_H__ */ | ||||
							
								
								
									
										1065
									
								
								src/nbtk/nbtk-scroll-bar.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1065
									
								
								src/nbtk/nbtk-scroll-bar.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										81
									
								
								src/nbtk/nbtk-scroll-bar.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/nbtk/nbtk-scroll-bar.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| /* | ||||
|  * nbtk-scroll-bar.h: Scroll bar actor | ||||
|  * | ||||
|  * Copyright 2008 OpenedHand | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: Chris Lord <chris@openedhand.com> | ||||
|  * Port to Nbtk by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_SCROLL_BAR_H__ | ||||
| #define __NBTK_SCROLL_BAR_H__ | ||||
|  | ||||
| #include <nbtk/nbtk-adjustment.h> | ||||
| #include <nbtk/nbtk-bin.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_SCROLL_BAR            (nbtk_scroll_bar_get_type()) | ||||
| #define NBTK_SCROLL_BAR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_SCROLL_BAR, NbtkScrollBar)) | ||||
| #define NBTK_IS_SCROLL_BAR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_SCROLL_BAR)) | ||||
| #define NBTK_SCROLL_BAR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_SCROLL_BAR, NbtkScrollBarClass)) | ||||
| #define NBTK_IS_SCROLL_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_SCROLL_BAR)) | ||||
| #define NBTK_SCROLL_BAR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_SCROLL_BAR, NbtkScrollBarClass)) | ||||
|  | ||||
| typedef struct _NbtkScrollBar          NbtkScrollBar; | ||||
| typedef struct _NbtkScrollBarPrivate   NbtkScrollBarPrivate; | ||||
| typedef struct _NbtkScrollBarClass     NbtkScrollBarClass; | ||||
|  | ||||
| /** | ||||
|  * NbtkScrollBar: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _NbtkScrollBar | ||||
| { | ||||
|   /*< private >*/ | ||||
|   NbtkBin parent_instance; | ||||
|  | ||||
|   NbtkScrollBarPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _NbtkScrollBarClass | ||||
| { | ||||
|   NbtkBinClass parent_class; | ||||
|  | ||||
|   /* signals */ | ||||
|   void (*scroll_start) (NbtkScrollBar *bar); | ||||
|   void (*scroll_stop)  (NbtkScrollBar *bar); | ||||
| }; | ||||
|  | ||||
| GType nbtk_scroll_bar_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| NbtkWidget *    nbtk_scroll_bar_new            (NbtkAdjustment *adjustment); | ||||
| void            nbtk_scroll_bar_set_adjustment (NbtkScrollBar  *bar, | ||||
|                                                 NbtkAdjustment *adjustment); | ||||
| NbtkAdjustment *nbtk_scroll_bar_get_adjustment (NbtkScrollBar  *bar); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_SCROLL_BAR_H__ */ | ||||
							
								
								
									
										829
									
								
								src/nbtk/nbtk-scroll-view.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										829
									
								
								src/nbtk/nbtk-scroll-view.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,829 @@ | ||||
| /* | ||||
|  * nbtk-scroll-view.h: Container with scroll-bars | ||||
|  * | ||||
|  * Copyright 2008 OpenedHand | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Chris Lord <chris@openedhand.com> | ||||
|  * Port to Nbtk by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "nbtk-scroll-view.h" | ||||
| #include "nbtk-marshal.h" | ||||
| #include "nbtk-scroll-bar.h" | ||||
| #include "nbtk-scrollable.h" | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| static void clutter_container_iface_init (ClutterContainerIface *iface); | ||||
|  | ||||
| static ClutterContainerIface *nbtk_scroll_view_parent_iface = NULL; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (NbtkScrollView, nbtk_scroll_view, NBTK_TYPE_BIN, | ||||
|                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, | ||||
|                                                 clutter_container_iface_init)) | ||||
|  | ||||
| #define SCROLL_VIEW_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ | ||||
|                                 NBTK_TYPE_SCROLL_VIEW, \ | ||||
|                                 NbtkScrollViewPrivate)) | ||||
|  | ||||
| /* Default width (or height - the narrow dimension) for the scrollbars*/ | ||||
| #define DEFAULT_SCROLLBAR_WIDTH 24 | ||||
|  | ||||
| struct _NbtkScrollViewPrivate | ||||
| { | ||||
|   /* a pointer to the child; this is actually stored | ||||
|    * inside NbtkBin:child, but we keep it to avoid | ||||
|    * calling nbtk_bin_get_child() every time we need it | ||||
|    */ | ||||
|   ClutterActor   *child; | ||||
|  | ||||
|   ClutterActor   *hscroll; | ||||
|   ClutterActor   *vscroll; | ||||
|  | ||||
|   gfloat          row_size; | ||||
|   gfloat          column_size; | ||||
|  | ||||
|   gboolean        row_size_set : 1; | ||||
|   gboolean        column_size_set : 1; | ||||
|   guint           mouse_scroll : 1; | ||||
| }; | ||||
|  | ||||
| enum { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_HSCROLL, | ||||
|   PROP_VSCROLL, | ||||
|   PROP_MOUSE_SCROLL | ||||
| }; | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_get_property (GObject *object, guint property_id, | ||||
|                                  GValue *value, GParamSpec *pspec) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv = ((NbtkScrollView *)object)->priv; | ||||
|  | ||||
|   switch (property_id) | ||||
|     { | ||||
|     case PROP_HSCROLL : | ||||
|       g_value_set_object (value, priv->hscroll); | ||||
|       break; | ||||
|     case PROP_VSCROLL : | ||||
|       g_value_set_object (value, priv->vscroll); | ||||
|       break; | ||||
|     case PROP_MOUSE_SCROLL: | ||||
|       g_value_set_boolean (value, priv->mouse_scroll); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_set_property (GObject *object, guint property_id, | ||||
|                                  const GValue *value, GParamSpec *pspec) | ||||
| { | ||||
|   switch (property_id) | ||||
|     { | ||||
|     case PROP_MOUSE_SCROLL: | ||||
|       nbtk_scroll_view_set_mouse_scrolling ((NbtkScrollView *) object, | ||||
|                                          g_value_get_boolean (value)); | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_dispose (GObject *object) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (object)->priv; | ||||
|  | ||||
|   priv->child = NULL; | ||||
|  | ||||
|   if (priv->vscroll) | ||||
|     { | ||||
|       clutter_actor_unparent (priv->vscroll); | ||||
|       priv->vscroll = NULL; | ||||
|     } | ||||
|  | ||||
|   if (priv->hscroll) | ||||
|     { | ||||
|       clutter_actor_unparent (priv->hscroll); | ||||
|       priv->hscroll = NULL; | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (nbtk_scroll_view_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_finalize (GObject *object) | ||||
| { | ||||
|   G_OBJECT_CLASS (nbtk_scroll_view_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_paint (ClutterActor *actor) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (actor)->priv; | ||||
|  | ||||
|   /* NbtkBin will paint the child */ | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_scroll_view_parent_class)->paint (actor); | ||||
|  | ||||
|   /* paint our custom children */ | ||||
|   if (CLUTTER_ACTOR_IS_VISIBLE (priv->hscroll)) | ||||
|     clutter_actor_paint (priv->hscroll); | ||||
|   if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll)) | ||||
|     clutter_actor_paint (priv->vscroll); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_pick (ClutterActor *actor, const ClutterColor *color) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (actor)->priv; | ||||
|  | ||||
|   /* Chain up so we get a bounding box pained (if we are reactive) */ | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_scroll_view_parent_class)->pick (actor, color); | ||||
|  | ||||
|   /* paint our custom children */ | ||||
|   if (CLUTTER_ACTOR_IS_VISIBLE (priv->hscroll)) | ||||
|     clutter_actor_paint (priv->hscroll); | ||||
|   if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll)) | ||||
|     clutter_actor_paint (priv->vscroll); | ||||
| } | ||||
|  | ||||
| static double | ||||
| get_scrollbar_width (NbtkScrollView *scroll_view) | ||||
| { | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (scroll_view)); | ||||
|   double result = DEFAULT_SCROLLBAR_WIDTH; | ||||
|  | ||||
|   shell_theme_node_get_length (theme_node, "scrollbar-width", FALSE, &result); | ||||
|  | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| static double | ||||
| get_scrollbar_height (NbtkScrollView *scroll_view) | ||||
| { | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (scroll_view)); | ||||
|   double result = DEFAULT_SCROLLBAR_WIDTH; | ||||
|  | ||||
|   shell_theme_node_get_length (theme_node, "scrollbar-height", FALSE, &result); | ||||
|  | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_get_preferred_width (ClutterActor *actor, | ||||
|                                       gfloat        for_height, | ||||
|                                       gfloat       *min_width_p, | ||||
|                                       gfloat       *natural_width_p) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (actor)->priv; | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); | ||||
|  | ||||
|   if (!priv->child) | ||||
|     return; | ||||
|  | ||||
|   shell_theme_node_adjust_for_height (theme_node, &for_height); | ||||
|  | ||||
|   /* Our natural width is the natural width of the child */ | ||||
|   clutter_actor_get_preferred_width (priv->child, | ||||
|                                      for_height, | ||||
|                                      NULL, | ||||
|                                      natural_width_p); | ||||
|  | ||||
|   /* Add space for the scroll-bar if we can determine it will be necessary */ | ||||
|   if ((for_height >= 0) && natural_width_p) | ||||
|     { | ||||
|       gfloat natural_height; | ||||
|  | ||||
|       clutter_actor_get_preferred_height (priv->child, -1.0, | ||||
|                                           NULL, | ||||
|                                           &natural_height); | ||||
|       if (for_height < natural_height) | ||||
|         *natural_width_p += get_scrollbar_width (NBTK_SCROLL_VIEW (actor)); | ||||
|     } | ||||
|  | ||||
|   if (min_width_p) | ||||
|     *min_width_p = 0; | ||||
|  | ||||
|   shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_get_preferred_height (ClutterActor *actor, | ||||
|                                        gfloat        for_width, | ||||
|                                        gfloat       *min_height_p, | ||||
|                                        gfloat       *natural_height_p) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (actor)->priv; | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); | ||||
|  | ||||
|   if (!priv->child) | ||||
|     return; | ||||
|  | ||||
|   shell_theme_node_adjust_for_width (theme_node, &for_width); | ||||
|  | ||||
|   /* Our natural height is the natural height of the child */ | ||||
|   clutter_actor_get_preferred_height (priv->child, | ||||
|                                       for_width, | ||||
|                                       NULL, | ||||
|                                       natural_height_p); | ||||
|  | ||||
|   /* Add space for the scroll-bar if we can determine it will be necessary */ | ||||
|   if ((for_width >= 0) && natural_height_p) | ||||
|     { | ||||
|       gfloat natural_width; | ||||
|  | ||||
|       clutter_actor_get_preferred_width (priv->child, -1.0, | ||||
|                                          NULL, | ||||
|                                          &natural_width); | ||||
|       if (for_width < natural_width) | ||||
|         *natural_height_p += get_scrollbar_height (NBTK_SCROLL_VIEW (actor)); | ||||
|     } | ||||
|  | ||||
|   if (min_height_p) | ||||
|     *min_height_p = 0; | ||||
|  | ||||
|   shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_allocate (ClutterActor          *actor, | ||||
|                            const ClutterActorBox *box, | ||||
|                            ClutterAllocationFlags flags) | ||||
| { | ||||
|   ClutterActorBox content_box, child_box; | ||||
|   ClutterActorClass *parent_parent_class; | ||||
|   gfloat avail_width, avail_height, sb_width, sb_height; | ||||
|  | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (actor)->priv; | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); | ||||
|  | ||||
|   /* Chain up to the parent's parent class | ||||
|    * | ||||
|    * We do this because we do not want NbtkBin to allocate the child, as we | ||||
|    * give it a different allocation later, depending on whether the scrollbars | ||||
|    * are visible | ||||
|    */ | ||||
|   parent_parent_class | ||||
|     = g_type_class_peek_parent (nbtk_scroll_view_parent_class); | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (parent_parent_class)-> | ||||
|     allocate (actor, box, flags); | ||||
|  | ||||
|  | ||||
|   shell_theme_node_get_content_box (theme_node, box, &content_box); | ||||
|  | ||||
|   avail_width = content_box.x2 - content_box.x1; | ||||
|   avail_height = content_box.y2 - content_box.y1; | ||||
|  | ||||
|   sb_width = get_scrollbar_width (NBTK_SCROLL_VIEW (actor)); | ||||
|   sb_height = get_scrollbar_width (NBTK_SCROLL_VIEW (actor)); | ||||
|  | ||||
|   if (!CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll)) | ||||
|     sb_width = 0; | ||||
|  | ||||
|   if (!CLUTTER_ACTOR_IS_VISIBLE (priv->hscroll)) | ||||
|     sb_height = 0; | ||||
|  | ||||
|   /* Vertical scrollbar */ | ||||
|   if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll)) | ||||
|     { | ||||
|       child_box.x1 = content_box.x2 - sb_width; | ||||
|       child_box.y1 = content_box.y1; | ||||
|       child_box.x2 = content_box.x2; | ||||
|       child_box.y2 = content_box.y2 - sb_height; | ||||
|  | ||||
|       clutter_actor_allocate (priv->vscroll, &child_box, flags); | ||||
|     } | ||||
|  | ||||
|   /* Horizontal scrollbar */ | ||||
|   if (CLUTTER_ACTOR_IS_VISIBLE (priv->hscroll)) | ||||
|     { | ||||
|       child_box.x1 = content_box.x1; | ||||
|       child_box.y1 = content_box.y2 - sb_height; | ||||
|       child_box.x2 = content_box.x2 - sb_width; | ||||
|       child_box.y2 = content_box.y2; | ||||
|  | ||||
|       clutter_actor_allocate (priv->hscroll, &child_box, flags); | ||||
|     } | ||||
|  | ||||
|  | ||||
|   /* Child */ | ||||
|   child_box.x1 = content_box.x1; | ||||
|   child_box.y1 = content_box.y1; | ||||
|   child_box.x2 = content_box.x2 - sb_width; | ||||
|   child_box.y2 = content_box.y2 - sb_height; | ||||
|  | ||||
|   if (priv->child) | ||||
|       clutter_actor_allocate (priv->child, &child_box, flags); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_style_changed (NbtkWidget *widget) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (widget)->priv; | ||||
|  | ||||
|   nbtk_widget_style_changed (NBTK_WIDGET (priv->hscroll)); | ||||
|   nbtk_widget_style_changed (NBTK_WIDGET (priv->vscroll)); | ||||
|  | ||||
|   NBTK_WIDGET_CLASS (nbtk_scroll_view_parent_class)->style_changed (widget); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| nbtk_scroll_view_scroll_event (ClutterActor        *self, | ||||
|                                ClutterScrollEvent  *event) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (self)->priv; | ||||
|   gdouble lower, value, upper, step; | ||||
|   NbtkAdjustment *vadjustment, *hadjustment; | ||||
|  | ||||
|   /* don't handle scroll events if requested not to */ | ||||
|   if (!priv->mouse_scroll) | ||||
|     return FALSE; | ||||
|  | ||||
|   hadjustment = nbtk_scroll_bar_get_adjustment (NBTK_SCROLL_BAR(priv->hscroll)); | ||||
|   vadjustment = nbtk_scroll_bar_get_adjustment (NBTK_SCROLL_BAR(priv->vscroll)); | ||||
|  | ||||
|   switch (event->direction) | ||||
|     { | ||||
|       case CLUTTER_SCROLL_UP: | ||||
|       case CLUTTER_SCROLL_DOWN: | ||||
|         if (vadjustment) | ||||
|           g_object_get (vadjustment, | ||||
|                         "lower", &lower, | ||||
|                         "step-increment", &step, | ||||
|                         "value", &value, | ||||
|                         "upper", &upper, | ||||
|                         NULL); | ||||
|         else | ||||
|           return FALSE; | ||||
|         break; | ||||
|       case CLUTTER_SCROLL_LEFT: | ||||
|       case CLUTTER_SCROLL_RIGHT: | ||||
|         if (vadjustment) | ||||
|           g_object_get (hadjustment, | ||||
|                         "lower", &lower, | ||||
|                         "step-increment", &step, | ||||
|                         "value", &value, | ||||
|                         "upper", &upper, | ||||
|                         NULL); | ||||
|           else | ||||
|             return FALSE; | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|   switch (event->direction) | ||||
|     { | ||||
|       case CLUTTER_SCROLL_UP: | ||||
|         if (value == lower) | ||||
|           return FALSE; | ||||
|         else | ||||
|           nbtk_adjustment_set_value (vadjustment, value - step); | ||||
|         break; | ||||
|       case CLUTTER_SCROLL_DOWN: | ||||
|         if (value == upper) | ||||
|           return FALSE; | ||||
|         else | ||||
|           nbtk_adjustment_set_value (vadjustment, value + step); | ||||
|         break; | ||||
|       case CLUTTER_SCROLL_LEFT: | ||||
|         if (value == lower) | ||||
|           return FALSE; | ||||
|         else | ||||
|           nbtk_adjustment_set_value (hadjustment, value - step); | ||||
|         break; | ||||
|       case CLUTTER_SCROLL_RIGHT: | ||||
|         if (value == upper) | ||||
|           return FALSE; | ||||
|         else | ||||
|           nbtk_adjustment_set_value (hadjustment, value + step); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_class_init (NbtkScrollViewClass *klass) | ||||
| { | ||||
|   GParamSpec *pspec; | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (NbtkScrollViewPrivate)); | ||||
|  | ||||
|   object_class->get_property = nbtk_scroll_view_get_property; | ||||
|   object_class->set_property = nbtk_scroll_view_set_property; | ||||
|   object_class->dispose= nbtk_scroll_view_dispose; | ||||
|   object_class->finalize = nbtk_scroll_view_finalize; | ||||
|  | ||||
|   actor_class->paint = nbtk_scroll_view_paint; | ||||
|   actor_class->pick = nbtk_scroll_view_pick; | ||||
|   actor_class->get_preferred_width = nbtk_scroll_view_get_preferred_width; | ||||
|   actor_class->get_preferred_height = nbtk_scroll_view_get_preferred_height; | ||||
|   actor_class->allocate = nbtk_scroll_view_allocate; | ||||
|   actor_class->scroll_event = nbtk_scroll_view_scroll_event; | ||||
|  | ||||
|   widget_class->style_changed = nbtk_scroll_view_style_changed; | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_HSCROLL, | ||||
|                                    g_param_spec_object ("hscroll", | ||||
|                                                         "NbtkScrollBar", | ||||
|                                                         "Horizontal scroll indicator", | ||||
|                                                         NBTK_TYPE_SCROLL_BAR, | ||||
|                                                         G_PARAM_READABLE)); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_VSCROLL, | ||||
|                                    g_param_spec_object ("vscroll", | ||||
|                                                        "NbtkScrollBar", | ||||
|                                                        "Vertical scroll indicator", | ||||
|                                                        NBTK_TYPE_SCROLL_BAR, | ||||
|                                                        G_PARAM_READABLE)); | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("enable-mouse-scrolling", | ||||
|                                 "Enable Mouse Scrolling", | ||||
|                                 "Enable automatic mouse wheel scrolling", | ||||
|                                 TRUE, | ||||
|                                 G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_MOUSE_SCROLL, | ||||
|                                    pspec); | ||||
|  | ||||
| } | ||||
|  | ||||
| static void | ||||
| child_adjustment_changed_cb (NbtkAdjustment *adjustment, | ||||
|                              ClutterActor   *bar) | ||||
| { | ||||
|   NbtkScrollView *scroll; | ||||
|   gdouble lower, upper, page_size; | ||||
|  | ||||
|   scroll = NBTK_SCROLL_VIEW (clutter_actor_get_parent (bar)); | ||||
|  | ||||
|   /* Determine if this scroll-bar should be visible */ | ||||
|   nbtk_adjustment_get_values (adjustment, NULL, | ||||
|                               &lower, &upper, | ||||
|                               NULL, NULL, | ||||
|                               &page_size); | ||||
|  | ||||
|   if ((upper - lower) > page_size) | ||||
|     clutter_actor_show (bar); | ||||
|   else | ||||
|     clutter_actor_hide (bar); | ||||
|  | ||||
|   /* Request a resize */ | ||||
|   clutter_actor_queue_relayout (CLUTTER_ACTOR (scroll)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| child_hadjustment_notify_cb (GObject *gobject, | ||||
|                              GParamSpec *arg1, | ||||
|                              gpointer user_data) | ||||
| { | ||||
|   NbtkAdjustment *hadjust; | ||||
|  | ||||
|   ClutterActor *actor = CLUTTER_ACTOR (gobject); | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (user_data)->priv; | ||||
|  | ||||
|   hadjust = nbtk_scroll_bar_get_adjustment (NBTK_SCROLL_BAR(priv->hscroll)); | ||||
|   if (hadjust) | ||||
|     g_signal_handlers_disconnect_by_func (hadjust, | ||||
|                                           child_adjustment_changed_cb, | ||||
|                                           priv->hscroll); | ||||
|  | ||||
|   nbtk_scrollable_get_adjustments (NBTK_SCROLLABLE (actor), &hadjust, NULL); | ||||
|   if (hadjust) | ||||
|     { | ||||
|       /* Force scroll step if neede. */ | ||||
|       if (priv->column_size_set) | ||||
|         { | ||||
|           g_object_set (hadjust, | ||||
|                         "step-increment", priv->column_size, | ||||
|                         NULL); | ||||
|         } | ||||
|  | ||||
|       nbtk_scroll_bar_set_adjustment (NBTK_SCROLL_BAR(priv->hscroll), hadjust); | ||||
|       g_signal_connect (hadjust, "changed", G_CALLBACK ( | ||||
|                         child_adjustment_changed_cb), priv->hscroll); | ||||
|       child_adjustment_changed_cb (hadjust, priv->hscroll); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| child_vadjustment_notify_cb (GObject *gobject, | ||||
|                              GParamSpec *arg1, | ||||
|                              gpointer user_data) | ||||
| { | ||||
|   NbtkAdjustment *vadjust; | ||||
|  | ||||
|   ClutterActor *actor = CLUTTER_ACTOR (gobject); | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (user_data)->priv; | ||||
|  | ||||
|   vadjust = nbtk_scroll_bar_get_adjustment (NBTK_SCROLL_BAR(priv->vscroll)); | ||||
|   if (vadjust) | ||||
|     g_signal_handlers_disconnect_by_func (vadjust, | ||||
|                                           child_adjustment_changed_cb, | ||||
|                                           priv->vscroll); | ||||
|  | ||||
|   nbtk_scrollable_get_adjustments (NBTK_SCROLLABLE(actor), NULL, &vadjust); | ||||
|   if (vadjust) | ||||
|     { | ||||
|       /* Force scroll step if neede. */ | ||||
|       if (priv->row_size_set) | ||||
|         { | ||||
|           g_object_set (vadjust, | ||||
|                         "step-increment", priv->row_size, | ||||
|                         NULL); | ||||
|         } | ||||
|  | ||||
|       nbtk_scroll_bar_set_adjustment (NBTK_SCROLL_BAR(priv->vscroll), vadjust); | ||||
|       g_signal_connect (vadjust, "changed", G_CALLBACK ( | ||||
|                         child_adjustment_changed_cb), priv->vscroll); | ||||
|       child_adjustment_changed_cb (vadjust, priv->vscroll); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_init (NbtkScrollView *self) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv = self->priv = SCROLL_VIEW_PRIVATE (self); | ||||
|  | ||||
|   priv->hscroll = CLUTTER_ACTOR (nbtk_scroll_bar_new (NULL)); | ||||
|   priv->vscroll = g_object_new (NBTK_TYPE_SCROLL_BAR, "vertical", TRUE, NULL); | ||||
|  | ||||
|   clutter_actor_set_parent (priv->hscroll, CLUTTER_ACTOR (self)); | ||||
|   clutter_actor_set_parent (priv->vscroll, CLUTTER_ACTOR (self)); | ||||
|  | ||||
|   /* mouse scroll is enabled by default, so we also need to be reactive */ | ||||
|   priv->mouse_scroll = TRUE; | ||||
|   g_object_set (G_OBJECT (self), "reactive", TRUE, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_add (ClutterContainer *container, | ||||
|                       ClutterActor     *actor) | ||||
| { | ||||
|   NbtkScrollView *self = NBTK_SCROLL_VIEW (container); | ||||
|   NbtkScrollViewPrivate *priv = self->priv; | ||||
|  | ||||
|   if (NBTK_IS_SCROLLABLE (actor)) | ||||
|     { | ||||
|       priv->child = actor; | ||||
|  | ||||
|       /* chain up to NbtkBin::add() */ | ||||
|       nbtk_scroll_view_parent_iface->add (container, actor); | ||||
|  | ||||
|       /* Get adjustments for scroll-bars */ | ||||
|       g_signal_connect (actor, "notify::hadjustment", | ||||
|                         G_CALLBACK (child_hadjustment_notify_cb), | ||||
|                         container); | ||||
|       g_signal_connect (actor, "notify::vadjustment", | ||||
|                         G_CALLBACK (child_vadjustment_notify_cb), | ||||
|                         container); | ||||
|       child_hadjustment_notify_cb (G_OBJECT (actor), NULL, container); | ||||
|       child_vadjustment_notify_cb (G_OBJECT (actor), NULL, container); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       g_warning ("Attempting to add an actor of type %s to " | ||||
|                  "a NbtkScrollView, but the actor does " | ||||
|                  "not implement NbtkScrollable.", | ||||
|                  g_type_name (G_OBJECT_TYPE (actor))); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_remove (ClutterContainer *container, | ||||
|                          ClutterActor     *actor) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (container)->priv; | ||||
|  | ||||
|   if (actor == priv->child) | ||||
|     { | ||||
|       g_object_ref (priv->child); | ||||
|  | ||||
|       /* chain up to NbtkBin::remove() */ | ||||
|       nbtk_scroll_view_parent_iface->remove (container, actor); | ||||
|  | ||||
|       g_signal_handlers_disconnect_by_func (priv->child, | ||||
|                                             child_hadjustment_notify_cb, | ||||
|                                             container); | ||||
|       g_signal_handlers_disconnect_by_func (priv->child, | ||||
|                                             child_vadjustment_notify_cb, | ||||
|                                             container); | ||||
|       nbtk_scrollable_set_adjustments ((NbtkScrollable*) priv->child, NULL, NULL); | ||||
|  | ||||
|       g_object_unref (priv->child); | ||||
|       priv->child = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_scroll_view_foreach_with_internals (ClutterContainer *container, | ||||
|                                          ClutterCallback   callback, | ||||
|                                          gpointer          user_data) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (container)->priv; | ||||
|  | ||||
|   if (priv->child != NULL) | ||||
|     callback (priv->child, user_data); | ||||
|  | ||||
|   if (priv->hscroll != NULL) | ||||
|     callback (priv->hscroll, user_data); | ||||
|  | ||||
|   if (priv->vscroll != NULL) | ||||
|     callback (priv->vscroll, user_data); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_container_iface_init (ClutterContainerIface *iface) | ||||
| { | ||||
|   /* store a pointer to the NbtkBin implementation of | ||||
|    * ClutterContainer so that we can chain up when | ||||
|    * overriding the methods | ||||
|    */ | ||||
|   nbtk_scroll_view_parent_iface = g_type_interface_peek_parent (iface); | ||||
|  | ||||
|   iface->add = nbtk_scroll_view_add; | ||||
|   iface->remove = nbtk_scroll_view_remove; | ||||
|   iface->foreach_with_internals = nbtk_scroll_view_foreach_with_internals; | ||||
| } | ||||
|  | ||||
| NbtkWidget * | ||||
| nbtk_scroll_view_new (void) | ||||
| { | ||||
|   return g_object_new (NBTK_TYPE_SCROLL_VIEW, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_scroll_view_get_hscroll_bar: | ||||
|  * @scroll: a #NbtkScrollView | ||||
|  * | ||||
|  * Gets the horizontal scrollbar of the scrollbiew | ||||
|  * | ||||
|  * Return value: (transfer none): the horizontal #NbtkScrollbar | ||||
|  */ | ||||
| ClutterActor * | ||||
| nbtk_scroll_view_get_hscroll_bar (NbtkScrollView *scroll) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_SCROLL_VIEW (scroll), NULL); | ||||
|  | ||||
|   return scroll->priv->hscroll; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_scroll_view_get_vscroll_bar: | ||||
|  * @scroll: a #NbtkScrollView | ||||
|  * | ||||
|  * Gets the vertical scrollbar of the scrollbiew | ||||
|  * | ||||
|  * Return value: (transfer none): the vertical #NbtkScrollbar | ||||
|  */ | ||||
| ClutterActor * | ||||
| nbtk_scroll_view_get_vscroll_bar (NbtkScrollView *scroll) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_SCROLL_VIEW (scroll), NULL); | ||||
|  | ||||
|   return scroll->priv->vscroll; | ||||
| } | ||||
|  | ||||
| gfloat | ||||
| nbtk_scroll_view_get_column_size (NbtkScrollView *scroll) | ||||
| { | ||||
|   NbtkAdjustment  *adjustment; | ||||
|   gdouble          column_size; | ||||
|  | ||||
|   g_return_val_if_fail (scroll, 0); | ||||
|  | ||||
|   adjustment = nbtk_scroll_bar_get_adjustment ( | ||||
|                 NBTK_SCROLL_BAR (scroll->priv->hscroll)); | ||||
|   g_object_get (adjustment, | ||||
|                 "step-increment", &column_size, | ||||
|                 NULL); | ||||
|  | ||||
|   return column_size; | ||||
| } | ||||
|  | ||||
| void | ||||
| nbtk_scroll_view_set_column_size (NbtkScrollView *scroll, | ||||
|                                   gfloat          column_size) | ||||
| { | ||||
|   NbtkAdjustment  *adjustment; | ||||
|  | ||||
|   g_return_if_fail (scroll); | ||||
|  | ||||
|   if (column_size < 0) | ||||
|     { | ||||
|       scroll->priv->column_size_set = FALSE; | ||||
|       scroll->priv->column_size = -1; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       scroll->priv->column_size_set = TRUE; | ||||
|       scroll->priv->column_size = column_size; | ||||
|  | ||||
|       adjustment = nbtk_scroll_bar_get_adjustment ( | ||||
|                     NBTK_SCROLL_BAR (scroll->priv->hscroll)); | ||||
|  | ||||
|       if (adjustment) | ||||
|         g_object_set (adjustment, | ||||
|                       "step-increment", (gdouble) scroll->priv->column_size, | ||||
|                       NULL); | ||||
|      } | ||||
| } | ||||
|  | ||||
| gfloat | ||||
| nbtk_scroll_view_get_row_size (NbtkScrollView *scroll) | ||||
| { | ||||
|   NbtkAdjustment  *adjustment; | ||||
|   gdouble row_size; | ||||
|  | ||||
|   g_return_val_if_fail (scroll, 0); | ||||
|  | ||||
|   adjustment = nbtk_scroll_bar_get_adjustment ( | ||||
|                 NBTK_SCROLL_BAR (scroll->priv->vscroll)); | ||||
|   g_object_get (adjustment, | ||||
|                 "step-increment", &row_size, | ||||
|                 NULL); | ||||
|  | ||||
|   return row_size; | ||||
| } | ||||
|  | ||||
| void | ||||
| nbtk_scroll_view_set_row_size (NbtkScrollView *scroll, | ||||
|                                gfloat          row_size) | ||||
| { | ||||
|   NbtkAdjustment  *adjustment; | ||||
|  | ||||
|   g_return_if_fail (scroll); | ||||
|  | ||||
|   if (row_size < 0) | ||||
|     { | ||||
|       scroll->priv->row_size_set = FALSE; | ||||
|       scroll->priv->row_size = -1; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       scroll->priv->row_size_set = TRUE; | ||||
|       scroll->priv->row_size = row_size; | ||||
|  | ||||
|       adjustment = nbtk_scroll_bar_get_adjustment ( | ||||
|                     NBTK_SCROLL_BAR (scroll->priv->vscroll)); | ||||
|  | ||||
|       if (adjustment) | ||||
|         g_object_set (adjustment, | ||||
|                       "step-increment", (gdouble) scroll->priv->row_size, | ||||
|                       NULL); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| nbtk_scroll_view_set_mouse_scrolling (NbtkScrollView *scroll, | ||||
|                                       gboolean        enabled) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_SCROLL_VIEW (scroll)); | ||||
|  | ||||
|   priv = NBTK_SCROLL_VIEW (scroll)->priv; | ||||
|  | ||||
|   if (priv->mouse_scroll != enabled) | ||||
|     { | ||||
|       priv->mouse_scroll = enabled; | ||||
|  | ||||
|       /* make sure we can receive mouse wheel events */ | ||||
|       if (enabled) | ||||
|         clutter_actor_set_reactive ((ClutterActor *) scroll, TRUE); | ||||
|     } | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| nbtk_scroll_view_get_mouse_scrolling (NbtkScrollView *scroll) | ||||
| { | ||||
|   NbtkScrollViewPrivate *priv; | ||||
|  | ||||
|   g_return_val_if_fail (NBTK_IS_SCROLL_VIEW (scroll), FALSE); | ||||
|  | ||||
|   priv = NBTK_SCROLL_VIEW (scroll)->priv; | ||||
|  | ||||
|   return priv->mouse_scroll; | ||||
| } | ||||
							
								
								
									
										87
									
								
								src/nbtk/nbtk-scroll-view.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/nbtk/nbtk-scroll-view.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| /* | ||||
|  * nbtk-scroll-view.h: Container with scroll-bars | ||||
|  * | ||||
|  * Copyright 2008 OpenedHand | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: Chris Lord <chris@openedhand.com> | ||||
|  * Port to Nbtk by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_SCROLL_VIEW_H__ | ||||
| #define __NBTK_SCROLL_VIEW_H__ | ||||
|  | ||||
| #include <nbtk/nbtk-bin.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_SCROLL_VIEW            (nbtk_scroll_view_get_type()) | ||||
| #define NBTK_SCROLL_VIEW(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_SCROLL_VIEW, NbtkScrollView)) | ||||
| #define NBTK_IS_SCROLL_VIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_SCROLL_VIEW)) | ||||
| #define NBTK_SCROLL_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_SCROLL_VIEW, NbtkScrollViewClass)) | ||||
| #define NBTK_IS_SCROLL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_SCROLL_VIEW)) | ||||
| #define NBTK_SCROLL_VIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_SCROLL_VIEW, NbtkScrollViewClass)) | ||||
|  | ||||
| typedef struct _NbtkScrollView          NbtkScrollView; | ||||
| typedef struct _NbtkScrollViewPrivate   NbtkScrollViewPrivate; | ||||
| typedef struct _NbtkScrollViewClass     NbtkScrollViewClass; | ||||
|  | ||||
| /** | ||||
|  * NbtkScrollView: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _NbtkScrollView | ||||
| { | ||||
|   /*< private >*/ | ||||
|   NbtkBin parent_instance; | ||||
|  | ||||
|   NbtkScrollViewPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _NbtkScrollViewClass | ||||
| { | ||||
|   NbtkBinClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType nbtk_scroll_view_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| NbtkWidget *  nbtk_scroll_view_new             (void); | ||||
|  | ||||
| ClutterActor *  nbtk_scroll_view_get_hscroll_bar (NbtkScrollView *scroll); | ||||
| ClutterActor *  nbtk_scroll_view_get_vscroll_bar (NbtkScrollView *scroll); | ||||
|  | ||||
| gfloat     nbtk_scroll_view_get_column_size (NbtkScrollView *scroll); | ||||
| void            nbtk_scroll_view_set_column_size (NbtkScrollView *scroll, | ||||
|                                                   gfloat          column_size); | ||||
|  | ||||
| gfloat     nbtk_scroll_view_get_row_size    (NbtkScrollView *scroll); | ||||
| void            nbtk_scroll_view_set_row_size    (NbtkScrollView *scroll, | ||||
|                                                   gfloat          row_size); | ||||
|  | ||||
| void nbtk_scroll_view_set_mouse_scrolling (NbtkScrollView *scroll, gboolean enabled); | ||||
| gboolean nbtk_scroll_view_get_mouse_scrolling (NbtkScrollView *scroll); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_SCROLL_VIEW_H__ */ | ||||
							
								
								
									
										96
									
								
								src/nbtk/nbtk-scrollable.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/nbtk/nbtk-scrollable.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| /* | ||||
|  * nbtk-scrollable.c: Scrollable interface | ||||
|  * | ||||
|  * Copyright 2008 OpenedHand | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  * Written by: Chris Lord <chris@openedhand.com> | ||||
|  * Port to Nbtk by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "nbtk-scrollable.h" | ||||
|  | ||||
| static void | ||||
| nbtk_scrollable_base_init (gpointer g_iface) | ||||
| { | ||||
|   static gboolean initialized = FALSE; | ||||
|  | ||||
|   if (!initialized) | ||||
|     { | ||||
|       g_object_interface_install_property (g_iface, | ||||
|                                    g_param_spec_object ("hadjustment", | ||||
|                                                         "NbtkAdjustment", | ||||
|                                                         "Horizontal adjustment", | ||||
|                                                         NBTK_TYPE_ADJUSTMENT, | ||||
|                                                         G_PARAM_READWRITE)); | ||||
|  | ||||
|       g_object_interface_install_property (g_iface, | ||||
|                                    g_param_spec_object ("vadjustment", | ||||
|                                                         "NbtkAdjustment", | ||||
|                                                         "Vertical adjustment", | ||||
|                                                         NBTK_TYPE_ADJUSTMENT, | ||||
|                                                         G_PARAM_READWRITE)); | ||||
|  | ||||
|       initialized = TRUE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| GType | ||||
| nbtk_scrollable_get_type (void) | ||||
| { | ||||
|   static GType type = 0; | ||||
|   if (type == 0) | ||||
|     { | ||||
|       static const GTypeInfo info = | ||||
|         { | ||||
|           sizeof (NbtkScrollableInterface), | ||||
|           nbtk_scrollable_base_init,        /* base_init */ | ||||
|           NULL, | ||||
|         }; | ||||
|       type = g_type_register_static (G_TYPE_INTERFACE, | ||||
|                                      "NbtkScrollable", &info, 0); | ||||
|     } | ||||
|   return type; | ||||
| } | ||||
|  | ||||
| void | ||||
| nbtk_scrollable_set_adjustments (NbtkScrollable *scrollable, | ||||
|                                  NbtkAdjustment *hadjustment, | ||||
|                                  NbtkAdjustment *vadjustment) | ||||
| { | ||||
|   NBTK_SCROLLABLE_GET_INTERFACE (scrollable)->set_adjustments (scrollable, | ||||
|                                                                hadjustment, | ||||
|                                                                vadjustment); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_scroll_bar_get_adjustments: | ||||
|  * @hadjustment: (transfer none) (out) (allow-none): location to store the horizontal adjustment, or %NULL | ||||
|  * @vadjustment: (transfer none) (out) (allow-none): location to store the vertical adjustment, or %NULL | ||||
|  * | ||||
|  * Gets the adjustment objects that store the offsets of the scrollable widget | ||||
|  * into its possible scrolling area. | ||||
|  */ | ||||
| void | ||||
| nbtk_scrollable_get_adjustments (NbtkScrollable *scrollable, | ||||
|                                  NbtkAdjustment **hadjustment, | ||||
|                                  NbtkAdjustment **vadjustment) | ||||
| { | ||||
|   NBTK_SCROLLABLE_GET_INTERFACE (scrollable)->get_adjustments (scrollable, | ||||
|                                                                hadjustment, | ||||
|                                                                vadjustment); | ||||
| } | ||||
							
								
								
									
										69
									
								
								src/nbtk/nbtk-scrollable.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/nbtk/nbtk-scrollable.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* | ||||
|  * nbtk-scrollable.h: Scrollable interface | ||||
|  * | ||||
|  * Copyright 2008 OpenedHand | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: Chris Lord <chris@openedhand.com> | ||||
|  * Port to Nbtk by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_SCROLLABLE_H__ | ||||
| #define __NBTK_SCROLLABLE_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <nbtk/nbtk-adjustment.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_SCROLLABLE                (nbtk_scrollable_get_type ()) | ||||
| #define NBTK_SCROLLABLE(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_SCROLLABLE, NbtkScrollable)) | ||||
| #define NBTK_IS_SCROLLABLE(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_SCROLLABLE)) | ||||
| #define NBTK_SCROLLABLE_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), NBTK_TYPE_SCROLLABLE, NbtkScrollableInterface)) | ||||
|  | ||||
| typedef struct _NbtkScrollable NbtkScrollable; /* Dummy object */ | ||||
| typedef struct _NbtkScrollableInterface NbtkScrollableInterface; | ||||
|  | ||||
| struct _NbtkScrollableInterface | ||||
| { | ||||
|   GTypeInterface parent; | ||||
|  | ||||
|   void (* set_adjustments) (NbtkScrollable  *scrollable, | ||||
|                             NbtkAdjustment  *hadjustment, | ||||
|                             NbtkAdjustment  *vadjustment); | ||||
|   void (* get_adjustments) (NbtkScrollable  *scrollable, | ||||
|                             NbtkAdjustment **hadjustment, | ||||
|                             NbtkAdjustment **vadjustment); | ||||
| }; | ||||
|  | ||||
| GType nbtk_scrollable_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| void nbtk_scrollable_set_adjustments (NbtkScrollable  *scrollable, | ||||
|                                       NbtkAdjustment  *hadjustment, | ||||
|                                       NbtkAdjustment  *vadjustment); | ||||
| void nbtk_scrollable_get_adjustments (NbtkScrollable  *scrollable, | ||||
|                                       NbtkAdjustment **hadjustment, | ||||
|                                       NbtkAdjustment **vadjustment); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_SCROLLABLE_H__ */ | ||||
							
								
								
									
										575
									
								
								src/nbtk/nbtk-subtexture.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										575
									
								
								src/nbtk/nbtk-subtexture.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,575 @@ | ||||
| /* | ||||
|  * nbtk-subtexture.h: Class to wrap a texture and "subframe" it. | ||||
|  * based on | ||||
|  * nbtk-texture-frame.c: Expandible texture actor | ||||
|  * | ||||
|  * Copyright 2007 OpenedHand | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "nbtk-subtexture.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_PARENT_TEXTURE, | ||||
|  | ||||
|   PROP_TOP, | ||||
|   PROP_LEFT, | ||||
|   PROP_WIDTH, | ||||
|   PROP_HEIGHT | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (NbtkSubtexture, nbtk_subtexture, CLUTTER_TYPE_ACTOR); | ||||
|  | ||||
| #define NBTK_SUBTEXTURE_GET_PRIVATE(obj)     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_SUBTEXTURE, NbtkSubtexturePrivate)) | ||||
|  | ||||
| struct _NbtkSubtexturePrivate | ||||
| { | ||||
|   ClutterTexture *parent_texture; | ||||
|  | ||||
|   int left; | ||||
|   int top; | ||||
|   int width; | ||||
|   int height; | ||||
|  | ||||
|   CoglHandle material; | ||||
| }; | ||||
|  | ||||
| static void | ||||
| nbtk_subtexture_get_preferred_width (ClutterActor *self, | ||||
|                                         gfloat   for_height, | ||||
|                                         gfloat  *min_width_p, | ||||
|                                         gfloat  *natural_width_p) | ||||
| { | ||||
|   NbtkSubtexturePrivate *priv = NBTK_SUBTEXTURE (self)->priv; | ||||
|  | ||||
|   if (G_UNLIKELY (priv->parent_texture == NULL)) | ||||
|     { | ||||
|       if (min_width_p) | ||||
|         *min_width_p = 0; | ||||
|  | ||||
|       if (natural_width_p) | ||||
|         *natural_width_p = 0; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
| 	if (min_width_p) | ||||
| 		*min_width_p = priv->width; | ||||
| 	if (natural_width_p) | ||||
| 		*natural_width_p = priv->width; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_subtexture_get_preferred_height (ClutterActor *self, | ||||
|                                          gfloat   for_width, | ||||
|                                          gfloat  *min_height_p, | ||||
|                                          gfloat  *natural_height_p) | ||||
| { | ||||
|   NbtkSubtexturePrivate *priv = NBTK_SUBTEXTURE (self)->priv; | ||||
|  | ||||
|   if (G_UNLIKELY (priv->parent_texture == NULL)) | ||||
|     { | ||||
|       if (min_height_p) | ||||
|         *min_height_p = 0; | ||||
|  | ||||
|       if (natural_height_p) | ||||
|         *natural_height_p = 0; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
| 	if (min_height_p) | ||||
| 		*min_height_p = priv->height; | ||||
| 	if (natural_height_p) | ||||
| 		*natural_height_p = priv->height; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_subtexture_realize (ClutterActor *self) | ||||
| { | ||||
|   NbtkSubtexturePrivate *priv = NBTK_SUBTEXTURE (self)->priv; | ||||
|  | ||||
|   if (priv->material != COGL_INVALID_HANDLE) | ||||
|     return; | ||||
|  | ||||
|   priv->material = cogl_material_new (); | ||||
|  | ||||
|   CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_subtexture_unrealize (ClutterActor *self) | ||||
| { | ||||
|   NbtkSubtexturePrivate *priv = NBTK_SUBTEXTURE (self)->priv; | ||||
|  | ||||
|   if (priv->material == COGL_INVALID_HANDLE) | ||||
|     return; | ||||
|  | ||||
|   cogl_material_unref (priv->material); | ||||
|   priv->material = COGL_INVALID_HANDLE; | ||||
|  | ||||
|   CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_subtexture_paint (ClutterActor *self) | ||||
| { | ||||
|   NbtkSubtexturePrivate *priv = NBTK_SUBTEXTURE (self)->priv; | ||||
|   CoglHandle cogl_texture = COGL_INVALID_HANDLE; | ||||
|   ClutterActorBox box = { 0, 0, 0, 0 }; | ||||
|   gfloat tx1, ty1, tx2, ty2, tex_width, tex_height, width, height; | ||||
|   guint8 opacity; | ||||
|  | ||||
|   /* no need to paint stuff if we don't have a texture */ | ||||
|   if (G_UNLIKELY (priv->parent_texture == NULL)) | ||||
|     return; | ||||
|  | ||||
|   /* parent texture may have been hidden, so need to make sure it gets | ||||
|    * realized | ||||
|    */ | ||||
|   if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_texture)) | ||||
|     clutter_actor_realize (CLUTTER_ACTOR (priv->parent_texture)); | ||||
|  | ||||
|   cogl_texture = clutter_texture_get_cogl_texture (priv->parent_texture); | ||||
|   if (cogl_texture == COGL_INVALID_HANDLE) | ||||
|     return; | ||||
|  | ||||
|   tex_width  = cogl_texture_get_width (cogl_texture); | ||||
|   tex_height = cogl_texture_get_height (cogl_texture); | ||||
|  | ||||
|   clutter_actor_get_allocation_box (self, &box); | ||||
|  | ||||
|   width = box.x2 - box.x1; | ||||
|   height = box.y2 - box.y1; | ||||
|  | ||||
|   tx1 = 1.0 *  priv->left / tex_width; | ||||
|   ty1 = 1.0 * priv->top / tex_height; | ||||
|  | ||||
|   tx2 = 1.0 * (priv->left + priv->width) / tex_width; | ||||
|   ty2 = 1.0 * (priv->top + priv->height) / tex_height; | ||||
|  | ||||
|  | ||||
|   opacity = clutter_actor_get_paint_opacity (self); | ||||
|  | ||||
|   g_assert (priv->material != COGL_INVALID_HANDLE); | ||||
|  | ||||
|   /* set the source material using the parent texture's COGL handle */ | ||||
|   cogl_material_set_color4ub (priv->material, 255, 255, 255, opacity); | ||||
|   cogl_material_set_layer (priv->material, 0, cogl_texture); | ||||
|   cogl_set_source (priv->material); | ||||
|  | ||||
|   cogl_rectangle_with_texture_coords (0,0, (float)width, (float)height, | ||||
| 		tx1, ty1, tx2, ty2); | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| nbtk_subtexture_set_frame_internal (NbtkSubtexture *frame, | ||||
|                                        int            left, | ||||
|                                        int            top, | ||||
|                                        int            width, | ||||
|                                        int            height) | ||||
| { | ||||
|   NbtkSubtexturePrivate *priv = frame->priv; | ||||
|   GObject *gobject = G_OBJECT (frame); | ||||
|   gboolean changed = FALSE; | ||||
|  | ||||
|   g_object_freeze_notify (gobject); | ||||
|  | ||||
|   if (priv->top != top) | ||||
|     { | ||||
|       priv->top = top; | ||||
|       g_object_notify (gobject, "top"); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (priv->left != left) | ||||
|     { | ||||
|       priv->left = left; | ||||
|       g_object_notify (gobject, "left"); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (priv->width != width) | ||||
|     { | ||||
|       priv->width = width; | ||||
|       g_object_notify (gobject, "width"); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (priv->height != height) | ||||
|     { | ||||
|       priv->height = height; | ||||
|       g_object_notify (gobject, "height"); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (changed && CLUTTER_ACTOR_IS_VISIBLE (frame)) | ||||
|     clutter_actor_queue_redraw (CLUTTER_ACTOR (frame)); | ||||
|  | ||||
|   g_object_thaw_notify (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_subtexture_set_property (GObject      *gobject, | ||||
|                                  guint         prop_id, | ||||
|                                  const GValue *value, | ||||
|                                  GParamSpec   *pspec) | ||||
| { | ||||
|   NbtkSubtexture *frame = NBTK_SUBTEXTURE (gobject); | ||||
|   NbtkSubtexturePrivate *priv = frame->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_PARENT_TEXTURE: | ||||
|       nbtk_subtexture_set_parent_texture (frame, | ||||
|                                              g_value_get_object (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TOP: | ||||
|       nbtk_subtexture_set_frame_internal (frame, | ||||
|                                              priv->left, | ||||
|                                              g_value_get_int (value), | ||||
|                                              priv->width, | ||||
|                                              priv->height); | ||||
|       break; | ||||
|  | ||||
|     case PROP_LEFT: | ||||
|       nbtk_subtexture_set_frame_internal (frame, | ||||
|                                              g_value_get_int (value), | ||||
|                                              priv->top, | ||||
|                                              priv->width, | ||||
|                                              priv->height); | ||||
|       break; | ||||
|  | ||||
|     case PROP_WIDTH: | ||||
|       nbtk_subtexture_set_frame_internal (frame, | ||||
|                                              priv->left, | ||||
|                                              priv->top, | ||||
|                                              g_value_get_int (value), | ||||
|                                              priv->height); | ||||
|       break; | ||||
|  | ||||
|     case PROP_HEIGHT: | ||||
|       nbtk_subtexture_set_frame_internal (frame, | ||||
|                                              priv->left, | ||||
|                                              priv->top, | ||||
|                                              priv->width, | ||||
|                                              g_value_get_int (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_subtexture_get_property (GObject    *gobject, | ||||
|                                  guint       prop_id, | ||||
|                                  GValue     *value, | ||||
|                                  GParamSpec *pspec) | ||||
| { | ||||
|   NbtkSubtexturePrivate *priv = NBTK_SUBTEXTURE (gobject)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_PARENT_TEXTURE: | ||||
|       g_value_set_object (value, priv->parent_texture); | ||||
|       break; | ||||
|  | ||||
|     case PROP_LEFT: | ||||
|       g_value_set_int (value, priv->left); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TOP: | ||||
|       g_value_set_int (value, priv->top); | ||||
|       break; | ||||
|  | ||||
|     case PROP_WIDTH: | ||||
|       g_value_set_int (value, priv->width); | ||||
|       break; | ||||
|  | ||||
|     case PROP_HEIGHT: | ||||
|       g_value_set_int (value, priv->height); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_subtexture_dispose (GObject *gobject) | ||||
| { | ||||
|   NbtkSubtexturePrivate *priv = NBTK_SUBTEXTURE (gobject)->priv; | ||||
|  | ||||
|   if (priv->parent_texture) | ||||
|     { | ||||
|       g_object_unref (priv->parent_texture); | ||||
|       priv->parent_texture = NULL; | ||||
|     } | ||||
|  | ||||
|   if (priv->material) | ||||
|     { | ||||
|       cogl_material_unref (priv->material); | ||||
|       priv->material = COGL_INVALID_HANDLE; | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (nbtk_subtexture_parent_class)->dispose (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_subtexture_class_init (NbtkSubtextureClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (gobject_class, sizeof (NbtkSubtexturePrivate)); | ||||
|  | ||||
|   actor_class->get_preferred_width = | ||||
|     nbtk_subtexture_get_preferred_width; | ||||
|   actor_class->get_preferred_height = | ||||
|     nbtk_subtexture_get_preferred_height; | ||||
|   actor_class->realize = nbtk_subtexture_realize; | ||||
|   actor_class->unrealize = nbtk_subtexture_unrealize; | ||||
|   actor_class->paint = nbtk_subtexture_paint; | ||||
|  | ||||
|   gobject_class->set_property = nbtk_subtexture_set_property; | ||||
|   gobject_class->get_property = nbtk_subtexture_get_property; | ||||
|   gobject_class->dispose = nbtk_subtexture_dispose; | ||||
|  | ||||
|   pspec = g_param_spec_object ("parent-texture", | ||||
|                                "Parent Texture", | ||||
|                                "The parent ClutterTexture", | ||||
|                                CLUTTER_TYPE_TEXTURE, | ||||
|                                G_PARAM_READWRITE | | ||||
|                                G_PARAM_CONSTRUCT); | ||||
|   g_object_class_install_property (gobject_class, PROP_PARENT_TEXTURE, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_int ("left", | ||||
|                               "Left", | ||||
|                               "Left offset", | ||||
| 			      0, G_MAXINT, | ||||
|                               0, | ||||
|                               G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_LEFT, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_int ("top", | ||||
|                               "Top", | ||||
|                               "Top offset", | ||||
|                               0, G_MAXINT, | ||||
|                               0, | ||||
|                               G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_TOP, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_int ("width", | ||||
|                               "Width", | ||||
|                               "Width", | ||||
|                               0, G_MAXINT, | ||||
|                               0, | ||||
|                               G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_WIDTH, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_int ("height", | ||||
|                               "Height", | ||||
|                               "Height", | ||||
|                               0, G_MAXINT, | ||||
|                               0, | ||||
|                               G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_HEIGHT, pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_subtexture_init (NbtkSubtexture *self) | ||||
| { | ||||
|   NbtkSubtexturePrivate *priv; | ||||
|  | ||||
|   self->priv = priv = NBTK_SUBTEXTURE_GET_PRIVATE (self); | ||||
|  | ||||
|   priv->material = COGL_INVALID_HANDLE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_subtexture_new: | ||||
|  * @texture: a #ClutterTexture or %NULL | ||||
|  * @left: left | ||||
|  * @top: top | ||||
|  * @width: width | ||||
|  * @height: height | ||||
|  * | ||||
|  * A #NbtkSubtexture is a specialized texture that efficiently clones | ||||
|  * an area of the given @texture while keeping preserving portions of the | ||||
|  * same texture. | ||||
|  * | ||||
|  * A #NbtkSubtexture can be used to make a rectangular texture fit a | ||||
|  * given size without stretching its borders. | ||||
|  * | ||||
|  * Return value: the newly created #NbtkSubtexture | ||||
|  */ | ||||
| ClutterActor* | ||||
| nbtk_subtexture_new (ClutterTexture *texture, | ||||
| 			gint          left, | ||||
| 			gint          top, | ||||
| 			gint          width, | ||||
| 			gint          height) | ||||
| { | ||||
|   g_return_val_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture), NULL); | ||||
|  | ||||
|   return g_object_new (NBTK_TYPE_SUBTEXTURE, | ||||
| 		       "parent-texture", texture, | ||||
| 		       "top", top, | ||||
| 		       "left", left, | ||||
| 		       "width", width, | ||||
| 		       "height", height, | ||||
| 		       NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_subtexture_get_parent_texture: | ||||
|  * @frame: A #NbtkSubtexture | ||||
|  * | ||||
|  * Return the texture used by the #NbtkSubtexture | ||||
|  * | ||||
|  * Returns: (transfer none): a #ClutterTexture owned by the #NbtkSubtexture | ||||
|  */ | ||||
| ClutterTexture * | ||||
| nbtk_subtexture_get_parent_texture (NbtkSubtexture *frame) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_SUBTEXTURE (frame), NULL); | ||||
|  | ||||
|   return frame->priv->parent_texture; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_subtexture_set_parent_texture: | ||||
|  * @frame: A #NbtkSubtexture | ||||
|  * @texture: A #ClutterTexture | ||||
|  * | ||||
|  * Set the #ClutterTexture used by this #NbtkSubtexture | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| nbtk_subtexture_set_parent_texture (NbtkSubtexture *frame, | ||||
|                                        ClutterTexture   *texture) | ||||
| { | ||||
|   NbtkSubtexturePrivate *priv; | ||||
|   gboolean was_visible; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_SUBTEXTURE (frame)); | ||||
|   g_return_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture)); | ||||
|  | ||||
|   priv = frame->priv; | ||||
|  | ||||
|   was_visible = CLUTTER_ACTOR_IS_VISIBLE (frame); | ||||
|  | ||||
|   if (priv->parent_texture == texture) | ||||
|     return; | ||||
|  | ||||
|   if (priv->parent_texture) | ||||
|     { | ||||
|       g_object_unref (priv->parent_texture); | ||||
|       priv->parent_texture = NULL; | ||||
|  | ||||
|       if (was_visible) | ||||
|         clutter_actor_hide (CLUTTER_ACTOR (frame)); | ||||
|     } | ||||
|  | ||||
|   if (texture) | ||||
|     { | ||||
|       priv->parent_texture = g_object_ref (texture); | ||||
|  | ||||
|       if (was_visible && CLUTTER_ACTOR_IS_VISIBLE (priv->parent_texture)) | ||||
|         clutter_actor_show (CLUTTER_ACTOR (frame)); | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_relayout (CLUTTER_ACTOR (frame)); | ||||
|  | ||||
|   g_object_notify (G_OBJECT (frame), "parent-texture"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_subtexture_set_frame: | ||||
|  * @frame: A #NbtkSubtexture | ||||
|  * @left: left | ||||
|  * @top: top | ||||
|  * @width: width | ||||
|  * @height: height | ||||
|  * | ||||
|  * Set the frame of the subtexture | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| nbtk_subtexture_set_frame (NbtkSubtexture *frame, | ||||
|                               gint            left, | ||||
|                               gint            top, | ||||
|                               gint            width, | ||||
|                               gint            height) | ||||
| { | ||||
|   g_return_if_fail (NBTK_IS_SUBTEXTURE (frame)); | ||||
|  | ||||
|   nbtk_subtexture_set_frame_internal (frame, left, top, width, height); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_subtexture_get_frame: | ||||
|  * @frame: A #NbtkSubtexture | ||||
|  * @left: left | ||||
|  * @top: top | ||||
|  * @width: width | ||||
|  * @height: height | ||||
|  * | ||||
|  * Retrieve the current frame. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| nbtk_subtexture_get_frame (NbtkSubtexture *frame, | ||||
|                               gint           *left, | ||||
|                               gint           *top, | ||||
|                               gint           *width, | ||||
|                               gint           *height) | ||||
| { | ||||
|   NbtkSubtexturePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_SUBTEXTURE (frame)); | ||||
|  | ||||
|   priv = frame->priv; | ||||
|  | ||||
|   if (top) | ||||
|     *top = priv->top; | ||||
|  | ||||
|   if (left) | ||||
|     *left = priv->left; | ||||
|  | ||||
|   if (width) | ||||
|     *width = priv->width; | ||||
|  | ||||
|   if (height) | ||||
|     *height = priv->height; | ||||
| } | ||||
							
								
								
									
										92
									
								
								src/nbtk/nbtk-subtexture.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/nbtk/nbtk-subtexture.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| /* | ||||
|  * nbtk-subtexture.h: Class to wrap a texture and "subframe" it. | ||||
|  * | ||||
|  * Based on | ||||
|  * nbtk-texture-frame.h: Expandible texture actor | ||||
|  * | ||||
|  * Copyright 2007, 2008 OpenedHand Ltd | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #ifndef __NBTK_SUBTEXTURE_H__ | ||||
| #define __NBTK_SUBTEXTURE_H__ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_SUBTEXTURE                 (nbtk_subtexture_get_type ()) | ||||
| #define NBTK_SUBTEXTURE(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_SUBTEXTURE, NbtkSubtexture)) | ||||
| #define NBTK_SUBTEXTURE_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_SUBTEXTURE, NbtkSubtextureClass)) | ||||
| #define NBTK_IS_SUBTEXTURE(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_SUBTEXTURE)) | ||||
| #define NBTK_IS_SUBTEXTURE_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_SUBTEXTURE)) | ||||
| #define NBTK_SUBTEXTURE_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_SUBTEXTURE, NbtkSubtextureClass)) | ||||
|  | ||||
| typedef struct _NbtkSubtexture                NbtkSubtexture; | ||||
| typedef struct _NbtkSubtexturePrivate         NbtkSubtexturePrivate; | ||||
| typedef struct _NbtkSubtextureClass           NbtkSubtextureClass; | ||||
|  | ||||
| /** | ||||
|  * NbtkSubtexture: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _NbtkSubtexture | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActor parent_instance; | ||||
|  | ||||
|   NbtkSubtexturePrivate    *priv; | ||||
| }; | ||||
|  | ||||
| struct _NbtkSubtextureClass | ||||
| { | ||||
|   ClutterActorClass parent_class; | ||||
|  | ||||
|   /* padding for future expansion */ | ||||
|   void (*_nbtk_box_1) (void); | ||||
|   void (*_nbtk_box_2) (void); | ||||
|   void (*_nbtk_box_3) (void); | ||||
|   void (*_nbtk_box_4) (void); | ||||
| }; | ||||
|  | ||||
| GType           nbtk_subtexture_get_type           (void) G_GNUC_CONST; | ||||
| ClutterActor *  nbtk_subtexture_new                (ClutterTexture   *texture, | ||||
|                                                        gint            top, | ||||
|                                                        gint            left, | ||||
|                                                        gint            width, | ||||
|                                                        gint            height); | ||||
| void            nbtk_subtexture_set_parent_texture (NbtkSubtexture *frame, | ||||
|                                                        ClutterTexture   *texture); | ||||
| ClutterTexture *nbtk_subtexture_get_parent_texture (NbtkSubtexture *frame); | ||||
| void            nbtk_subtexture_set_frame          (NbtkSubtexture *frame, | ||||
|                                                        gint            top, | ||||
|                                                        gint            left, | ||||
|                                                        gint            width, | ||||
|                                                        gint            height); | ||||
| void            nbtk_subtexture_get_frame          (NbtkSubtexture *frame, | ||||
|                                                        gint           *top, | ||||
|                                                        gint           *left, | ||||
|                                                        gint           *width, | ||||
|                                                        gint           *height); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_SUBTEXTURE_H__ */ | ||||
							
								
								
									
										456
									
								
								src/nbtk/nbtk-texture-cache.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										456
									
								
								src/nbtk/nbtk-texture-cache.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,456 @@ | ||||
| /* | ||||
|  * nbtk-widget.h: Base class for Nbtk actors | ||||
|  * | ||||
|  * Copyright 2007 OpenedHand | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:nbtk-texture-cache | ||||
|  * @short_description: A per-process store to cache textures | ||||
|  * | ||||
|  * #NbtkTextureCache allows an application to re-use an previously loaded | ||||
|  * textures. | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <glib.h> | ||||
| #include <glib-object.h> | ||||
| #include <gdk-pixbuf/gdk-pixbuf.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "nbtk-texture-cache.h" | ||||
| #include "nbtk-marshal.h" | ||||
| #include "nbtk-private.h" | ||||
| #include "nbtk-subtexture.h" | ||||
| G_DEFINE_TYPE (NbtkTextureCache, nbtk_texture_cache, G_TYPE_OBJECT) | ||||
|  | ||||
| #define TEXTURE_CACHE_PRIVATE(o) \ | ||||
|   (G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_TEXTURE_CACHE, NbtkTextureCachePrivate)) | ||||
|  | ||||
| typedef struct _NbtkTextureCachePrivate NbtkTextureCachePrivate; | ||||
|  | ||||
| struct _NbtkTextureCachePrivate | ||||
| { | ||||
|   GHashTable  *cache; | ||||
| }; | ||||
|  | ||||
| typedef struct FinalizedClosure | ||||
| { | ||||
|   gchar             *path; | ||||
|   NbtkTextureCache  *cache; | ||||
| } FinalizedClosure; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
| }; | ||||
|  | ||||
| static NbtkTextureCache* __cache_singleton = NULL; | ||||
|  | ||||
| /* | ||||
|  * Convention: posX with a value of -1 indicates whole texture | ||||
|  */ | ||||
| typedef struct NbtkTextureCacheItem { | ||||
|   char filename[256]; | ||||
|   int  width, height; | ||||
|   int  posX, posY; | ||||
|   ClutterActor *ptr; | ||||
| } NbtkTextureCacheItem; | ||||
|  | ||||
| static NbtkTextureCacheItem * | ||||
| nbtk_texture_cache_item_new (void) | ||||
| { | ||||
|   return g_slice_new0 (NbtkTextureCacheItem); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_cache_item_free (NbtkTextureCacheItem *item) | ||||
| { | ||||
|   g_slice_free (NbtkTextureCacheItem, item); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_cache_set_property (GObject      *object, | ||||
|                                  guint         prop_id, | ||||
|                                  const GValue *value, | ||||
|                                  GParamSpec   *pspec) | ||||
| { | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_cache_get_property (GObject    *object, | ||||
|                                  guint       prop_id, | ||||
|                                  GValue     *value, | ||||
|                                  GParamSpec *pspec) | ||||
| { | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_cache_dispose (GObject *object) | ||||
| { | ||||
|   if (G_OBJECT_CLASS (nbtk_texture_cache_parent_class)->dispose) | ||||
|     G_OBJECT_CLASS (nbtk_texture_cache_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_cache_finalize (GObject *object) | ||||
| { | ||||
|   NbtkTextureCachePrivate *priv = TEXTURE_CACHE_PRIVATE(object); | ||||
|  | ||||
|   if (priv->cache) | ||||
|     { | ||||
|       g_hash_table_unref (priv->cache); | ||||
|       priv->cache = NULL; | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (nbtk_texture_cache_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_cache_class_init (NbtkTextureCacheClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (NbtkTextureCachePrivate)); | ||||
|  | ||||
|   object_class->get_property = nbtk_texture_cache_get_property; | ||||
|   object_class->set_property = nbtk_texture_cache_set_property; | ||||
|   object_class->dispose = nbtk_texture_cache_dispose; | ||||
|   object_class->finalize = nbtk_texture_cache_finalize; | ||||
|  | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_cache_init (NbtkTextureCache *self) | ||||
| { | ||||
|   NbtkTextureCachePrivate *priv = TEXTURE_CACHE_PRIVATE(self); | ||||
|  | ||||
|   priv->cache = g_hash_table_new_full (g_str_hash, | ||||
|                                        g_str_equal, | ||||
|                                        g_free, | ||||
|                                        NULL); | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_texture_cache_get_default: | ||||
|  * | ||||
|  * Returns the default texture cache. This is owned by Nbtk and should not be | ||||
|  * unreferenced or freed. | ||||
|  * | ||||
|  * Returns: (transfer none): a NbtkTextureCache | ||||
|  */ | ||||
| NbtkTextureCache* | ||||
| nbtk_texture_cache_get_default (void) | ||||
| { | ||||
|   if (G_UNLIKELY (__cache_singleton == NULL)) | ||||
|     __cache_singleton = g_object_new (NBTK_TYPE_TEXTURE_CACHE, NULL); | ||||
|  | ||||
|   return  __cache_singleton; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static void | ||||
| on_texure_finalized (gpointer data, | ||||
| 		     GObject *where_the_object_was) | ||||
| { | ||||
|   FinalizedClosure *closure = (FinalizedClosure *)data; | ||||
|   NbtkTextureCachePrivate *priv = TEXTURE_CACHE_PRIVATE(closure->cache); | ||||
|  | ||||
|   g_hash_table_remove (priv->cache, closure->path); | ||||
|  | ||||
|   g_free(closure->path); | ||||
|   g_free(closure); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * nbtk_texture_cache_get_size: | ||||
|  * @self: A #NbtkTextureCache | ||||
|  * | ||||
|  * Returns the number of items in the texture cache | ||||
|  * | ||||
|  * Returns: the current size of the cache | ||||
|  */ | ||||
| gint | ||||
| nbtk_texture_cache_get_size (NbtkTextureCache *self) | ||||
| { | ||||
|   NbtkTextureCachePrivate *priv = TEXTURE_CACHE_PRIVATE(self); | ||||
|  | ||||
|   return g_hash_table_size (priv->cache); | ||||
| } | ||||
|  | ||||
| static void | ||||
| add_texture_to_cache (NbtkTextureCache     *self, | ||||
|                       const gchar          *path, | ||||
|                       NbtkTextureCacheItem *item) | ||||
| { | ||||
|   /*  FinalizedClosure        *closure; */ | ||||
|   NbtkTextureCachePrivate *priv = TEXTURE_CACHE_PRIVATE(self); | ||||
|  | ||||
|   g_hash_table_insert (priv->cache, g_strdup (path), item); | ||||
|  | ||||
| #if 0 | ||||
|   /* Make sure we can remove from hash */ | ||||
|   closure = g_new0 (FinalizedClosure, 1); | ||||
|   closure->path = g_strdup (path); | ||||
|   closure->cache = self; | ||||
|  | ||||
|   g_object_weak_ref (G_OBJECT (res), on_texure_finalized, closure); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /* NOTE: you should unref the returned texture when not needed */ | ||||
|  | ||||
| /** | ||||
|  * nbtk_texture_cache_get_texture: | ||||
|  * @self: A #NbtkTextureCache | ||||
|  * @path: A path to a image file | ||||
|  * @want_clone: ignored | ||||
|  * | ||||
|  * Create a new ClutterTexture with the specified image. Adds the image to the | ||||
|  * cache if the image had not been previously loaded. Subsequent calls with | ||||
|  * the same image path will return a new ClutterTexture with the previously | ||||
|  * loaded image. | ||||
|  * | ||||
|  * Returns: (transfer none): a newly created ClutterTexture | ||||
|  */ | ||||
| ClutterTexture* | ||||
| nbtk_texture_cache_get_texture (NbtkTextureCache *self, | ||||
|                                 const gchar      *path, | ||||
|                                 gboolean          want_clone) | ||||
| { | ||||
|   ClutterActor *texture; | ||||
|   CoglHandle *handle; | ||||
|   NbtkTextureCachePrivate *priv; | ||||
|   NbtkTextureCacheItem *item; | ||||
|  | ||||
|   g_return_val_if_fail (NBTK_IS_TEXTURE_CACHE (self), NULL); | ||||
|   g_return_val_if_fail (path != NULL, NULL); | ||||
|  | ||||
|  | ||||
|   priv = TEXTURE_CACHE_PRIVATE (self); | ||||
|  | ||||
|   if (want_clone) | ||||
|     g_warning ("The want_clone parameter of %s is now ignored. This function " | ||||
|                "always returns a new ClutterTexture", __FUNCTION__); | ||||
|  | ||||
|   item = g_hash_table_lookup (priv->cache, path); | ||||
|  | ||||
|   if (item && item->posX != -1) | ||||
|     { | ||||
|       GError *err = NULL; | ||||
|       /* | ||||
|        * We have a cache hit, but it's for a partial texture. The only | ||||
|        * sane option is to read it from disk and just don't cache it | ||||
|        * at all. | ||||
|        */ | ||||
|       return CLUTTER_TEXTURE(clutter_texture_new_from_file(path, &err)); | ||||
|     } | ||||
|   if (!item) | ||||
|     { | ||||
|       GError *err = NULL; | ||||
|  | ||||
|       item = nbtk_texture_cache_item_new (); | ||||
|       item->posX = -1; | ||||
|       item->posY = -1; | ||||
|       item->ptr = clutter_texture_new_from_file (path, &err); | ||||
|       clutter_texture_get_base_size (CLUTTER_TEXTURE (item->ptr), | ||||
|                                      &item->width, &item->height); | ||||
|  | ||||
|       if (!item->ptr) | ||||
|         { | ||||
|           if (err) | ||||
|             { | ||||
|               g_warning ("Error loading image: %s", err->message); | ||||
|               g_error_free (err); | ||||
|             } | ||||
|  | ||||
|           return NULL; | ||||
|         } | ||||
|  | ||||
|       add_texture_to_cache (self, path, item); | ||||
|     } | ||||
|  | ||||
|   texture = clutter_texture_new (); | ||||
|   handle = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (item->ptr)); | ||||
|   clutter_texture_set_cogl_texture ((ClutterTexture*) texture, handle); | ||||
|  | ||||
|   return (ClutterTexture*) texture; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * nbtk_texture_cache_get_actor: | ||||
|  * @self: A #NbtkTextureCache | ||||
|  * @path: A path to a image file | ||||
|  * | ||||
|  * Create a new ClutterSubTexture with the specified image. Adds the image to the | ||||
|  * cache if the image had not been previously loaded. Subsequent calls with | ||||
|  * the same image path will return a new ClutterTexture with the previously | ||||
|  * loaded image. | ||||
|  * | ||||
|  * Use this function if all you need is an actor for drawing. | ||||
|  * | ||||
|  * Returns: (transfer none): a newly created ClutterTexture | ||||
|  */ | ||||
| ClutterActor* | ||||
| nbtk_texture_cache_get_actor (NbtkTextureCache *self, | ||||
|                               const gchar      *path) | ||||
| { | ||||
|   NbtkTextureCachePrivate *priv; | ||||
|   NbtkTextureCacheItem *item; | ||||
|   GError *err = NULL; | ||||
|  | ||||
|   g_return_val_if_fail (NBTK_IS_TEXTURE_CACHE (self), NULL); | ||||
|   g_return_val_if_fail (path != NULL, NULL); | ||||
|  | ||||
|   priv = TEXTURE_CACHE_PRIVATE (self); | ||||
|  | ||||
|  | ||||
|   item = g_hash_table_lookup (priv->cache, path); | ||||
|  | ||||
|   if (item) | ||||
|     { | ||||
|       int posX = item->posX; | ||||
|       int posY = item->posY; | ||||
|       if (posX == -1) | ||||
|           posX = 0; | ||||
|       if (posY == -1) | ||||
|           posY = 0; | ||||
|       return nbtk_subtexture_new (CLUTTER_TEXTURE (item->ptr), posX, posY, | ||||
|                                   item->width, item->height); | ||||
|     } | ||||
|  | ||||
|   item = nbtk_texture_cache_item_new (); | ||||
|   item->posX = -1; | ||||
|   item->posY = -1; | ||||
|   item->ptr = clutter_texture_new_from_file (path, &err); | ||||
|   clutter_texture_get_base_size (CLUTTER_TEXTURE (item->ptr), | ||||
|                                  &item->width, &item->height); | ||||
|  | ||||
|   if (!item->ptr) | ||||
|     { | ||||
|       if (err) | ||||
|         { | ||||
|           g_warning ("Error loading image: %s", err->message); | ||||
|           g_error_free (err); | ||||
|         } | ||||
|  | ||||
|       return NULL; | ||||
|     } | ||||
|  | ||||
|   add_texture_to_cache (self, path, item); | ||||
|  | ||||
|   return nbtk_subtexture_new (CLUTTER_TEXTURE (item->ptr), 0, 0, item->width, | ||||
|                               item->height); | ||||
| } | ||||
|  | ||||
| void | ||||
| nbtk_texture_cache_load_cache (NbtkTextureCache *self, | ||||
|                                const gchar      *filename) | ||||
| { | ||||
|    FILE *file; | ||||
|    NbtkTextureCacheItem *element, head; | ||||
|    int ret; | ||||
|    ClutterActor *actor; | ||||
|    GError *error = NULL; | ||||
|    NbtkTextureCachePrivate *priv; | ||||
|  | ||||
|    g_return_if_fail (NBTK_IS_TEXTURE_CACHE (self)); | ||||
|    g_return_if_fail (filename != NULL); | ||||
|  | ||||
|    priv = TEXTURE_CACHE_PRIVATE (self); | ||||
|  | ||||
|    file = fopen(filename, "rm"); | ||||
|    if (!file) | ||||
|       return; | ||||
|  | ||||
|    ret = fread (&head, sizeof(NbtkTextureCacheItem), 1, file); | ||||
|    if (ret < 0) | ||||
|      { | ||||
|         fclose (file); | ||||
|         return; | ||||
|      } | ||||
|  | ||||
|    /* check if we already if this texture in the cache */ | ||||
|    if (g_hash_table_lookup (priv->cache, head.filename)) | ||||
|      { | ||||
|         /* skip it, we're done */ | ||||
|         fclose (file); | ||||
|         return; | ||||
|      } | ||||
|  | ||||
|    actor = clutter_texture_new_from_file (head.filename, &error); | ||||
|  | ||||
|    if (error) | ||||
|    { | ||||
|      g_critical (G_STRLOC ": Error opening cache image file: %s", | ||||
|                  error->message); | ||||
|      g_clear_error (&error); | ||||
|      fclose (file); | ||||
|      return; | ||||
|    } | ||||
|  | ||||
|    element = nbtk_texture_cache_item_new (); | ||||
|    element->posX = -1; | ||||
|    element->posY = -1; | ||||
|    element->ptr = actor; | ||||
|    strncpy (element->filename, head.filename, 256); | ||||
|    clutter_texture_get_base_size (CLUTTER_TEXTURE (element->ptr), | ||||
|                                   &element->width, &element->height); | ||||
|    g_hash_table_insert (priv->cache, element->filename, element); | ||||
|  | ||||
|    while (!feof (file)) | ||||
|      { | ||||
|         element = nbtk_texture_cache_item_new (); | ||||
|         ret = fread (element, sizeof (NbtkTextureCacheItem), 1, file); | ||||
|         if (ret < 1) | ||||
|           { | ||||
|              /* end of file */ | ||||
|              nbtk_texture_cache_item_free (element); | ||||
|              break; | ||||
|           } | ||||
|  | ||||
|         element->ptr = actor; | ||||
|  | ||||
|         if (g_hash_table_lookup (priv->cache, element->filename)) | ||||
|           { | ||||
|             /* file is already in the cache.... */ | ||||
|             nbtk_texture_cache_item_free (element); | ||||
|           } else { | ||||
|             g_hash_table_insert (priv->cache, element->filename, element); | ||||
|           } | ||||
|      } | ||||
| } | ||||
							
								
								
									
										94
									
								
								src/nbtk/nbtk-texture-cache.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/nbtk/nbtk-texture-cache.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /* | ||||
|  * nbtk-texture-cache.h: Cached textures object | ||||
|  * | ||||
|  * Copyright 2007 OpenedHand | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef _NBTK_TEXTURE_CACHE | ||||
| #define _NBTK_TEXTURE_CACHE | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_TEXTURE_CACHE nbtk_texture_cache_get_type() | ||||
|  | ||||
| #define NBTK_TEXTURE_CACHE(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ | ||||
|   NBTK_TYPE_TEXTURE_CACHE, NbtkTextureCache)) | ||||
|  | ||||
| #define NBTK_TEXTURE_CACHE_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_CAST ((klass), \ | ||||
|   NBTK_TYPE_TEXTURE_CACHE, NbtkTextureCacheClass)) | ||||
|  | ||||
| #define NBTK_IS_TEXTURE_CACHE(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ | ||||
|   NBTK_TYPE_TEXTURE_CACHE)) | ||||
|  | ||||
| #define NBTK_IS_TEXTURE_CACHE_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_TYPE ((klass), \ | ||||
|   NBTK_TYPE_TEXTURE_CACHE)) | ||||
|  | ||||
| #define NBTK_TEXTURE_CACHE_GET_CLASS(obj) \ | ||||
|   (G_TYPE_INSTANCE_GET_CLASS ((obj), \ | ||||
|   NBTK_TYPE_TEXTURE_CACHE, NbtkTextureCacheClass)) | ||||
|  | ||||
| /** | ||||
|  * NbtkTextureCache: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| typedef struct { | ||||
|     /*< private >*/ | ||||
|     GObject parent; | ||||
| } NbtkTextureCache; | ||||
|  | ||||
| typedef struct { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   void (* loaded)        (NbtkTextureCache *self, | ||||
|                           const gchar      *path, | ||||
|                           ClutterTexture   *texture); | ||||
|  | ||||
|   void (* error_loading) (NbtkTextureCache *self, | ||||
|                           GError           *error); | ||||
| } NbtkTextureCacheClass; | ||||
|  | ||||
| GType nbtk_texture_cache_get_type (void); | ||||
|  | ||||
| NbtkTextureCache* nbtk_texture_cache_get_default (void); | ||||
| ClutterTexture*   nbtk_texture_cache_get_texture (NbtkTextureCache *self, | ||||
|                                                   const gchar *path, | ||||
|                                                   gboolean want_clone); | ||||
| ClutterActor*     nbtk_texture_cache_get_actor (NbtkTextureCache *self, | ||||
|                                                   const gchar *path); | ||||
|  | ||||
| gint              nbtk_texture_cache_get_size    (NbtkTextureCache *self); | ||||
|  | ||||
| void nbtk_texture_cache_load_cache(NbtkTextureCache *self, const char *filename); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* _NBTK_TEXTURE_CACHE */ | ||||
							
								
								
									
										620
									
								
								src/nbtk/nbtk-texture-frame.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										620
									
								
								src/nbtk/nbtk-texture-frame.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,620 @@ | ||||
| /* | ||||
|  * nbtk-texture-frame.h: Expandible texture actor | ||||
|  * | ||||
|  * Copyright 2007 OpenedHand | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:nbtk-texture-frame | ||||
|  * @short_description: Stretch a texture to fit the entire allocation | ||||
|  * | ||||
|  * #NbtkTextureFrame | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
|  | ||||
| #include "nbtk-texture-frame.h" | ||||
| #include "nbtk-private.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_PARENT_TEXTURE, | ||||
|  | ||||
|   PROP_TOP, | ||||
|   PROP_RIGHT, | ||||
|   PROP_BOTTOM, | ||||
|   PROP_LEFT | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (NbtkTextureFrame, nbtk_texture_frame, CLUTTER_TYPE_ACTOR); | ||||
|  | ||||
| #define NBTK_TEXTURE_FRAME_GET_PRIVATE(obj)     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_TEXTURE_FRAME, NbtkTextureFramePrivate)) | ||||
|  | ||||
| struct _NbtkTextureFramePrivate | ||||
| { | ||||
|   ClutterTexture *parent_texture; | ||||
|  | ||||
|   gfloat top; | ||||
|   gfloat right; | ||||
|   gfloat bottom; | ||||
|   gfloat left; | ||||
| }; | ||||
|  | ||||
| static void | ||||
| nbtk_texture_frame_get_preferred_width (ClutterActor *self, | ||||
|                                         gfloat        for_height, | ||||
|                                         gfloat       *min_width_p, | ||||
|                                         gfloat       *natural_width_p) | ||||
| { | ||||
|   NbtkTextureFramePrivate *priv = NBTK_TEXTURE_FRAME (self)->priv; | ||||
|  | ||||
|   if (G_UNLIKELY (priv->parent_texture == NULL)) | ||||
|     { | ||||
|       if (min_width_p) | ||||
|         *min_width_p = 0; | ||||
|  | ||||
|       if (natural_width_p) | ||||
|         *natural_width_p = 0; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       ClutterActorClass *klass; | ||||
|  | ||||
|       /* by directly querying the parent texture's class implementation | ||||
|        * we are going around any override mechanism the parent texture | ||||
|        * might have in place, and we ask directly for the original | ||||
|        * preferred width | ||||
|        */ | ||||
|       klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture); | ||||
|       klass->get_preferred_width (CLUTTER_ACTOR (priv->parent_texture), | ||||
|                                   for_height, | ||||
|                                   min_width_p, | ||||
|                                   natural_width_p); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_frame_get_preferred_height (ClutterActor *self, | ||||
|                                          gfloat        for_width, | ||||
|                                          gfloat       *min_height_p, | ||||
|                                          gfloat       *natural_height_p) | ||||
| { | ||||
|   NbtkTextureFramePrivate *priv = NBTK_TEXTURE_FRAME (self)->priv; | ||||
|  | ||||
|   if (G_UNLIKELY (priv->parent_texture == NULL)) | ||||
|     { | ||||
|       if (min_height_p) | ||||
|         *min_height_p = 0; | ||||
|  | ||||
|       if (natural_height_p) | ||||
|         *natural_height_p = 0; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       ClutterActorClass *klass; | ||||
|  | ||||
|       /* by directly querying the parent texture's class implementation | ||||
|        * we are going around any override mechanism the parent texture | ||||
|        * might have in place, and we ask directly for the original | ||||
|        * preferred height | ||||
|        */ | ||||
|       klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture); | ||||
|       klass->get_preferred_height (CLUTTER_ACTOR (priv->parent_texture), | ||||
|                                    for_width, | ||||
|                                    min_height_p, | ||||
|                                    natural_height_p); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_frame_paint (ClutterActor *self) | ||||
| { | ||||
|   NbtkTextureFramePrivate *priv = NBTK_TEXTURE_FRAME (self)->priv; | ||||
|   CoglHandle cogl_texture = COGL_INVALID_HANDLE; | ||||
|   CoglHandle cogl_material = COGL_INVALID_HANDLE; | ||||
|   ClutterActorBox box = { 0, }; | ||||
|   gfloat width, height; | ||||
|   gfloat tex_width, tex_height; | ||||
|   gfloat ex, ey; | ||||
|   gfloat tx1, ty1, tx2, ty2; | ||||
|   guint8 opacity; | ||||
|  | ||||
|   /* no need to paint stuff if we don't have a texture */ | ||||
|   if (G_UNLIKELY (priv->parent_texture == NULL)) | ||||
|     return; | ||||
|  | ||||
|   /* parent texture may have been hidden, so need to make sure it gets | ||||
|    * realized | ||||
|    */ | ||||
|   if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_texture)) | ||||
|     clutter_actor_realize (CLUTTER_ACTOR (priv->parent_texture)); | ||||
|  | ||||
|   cogl_texture = clutter_texture_get_cogl_texture (priv->parent_texture); | ||||
|   if (cogl_texture == COGL_INVALID_HANDLE) | ||||
|     return; | ||||
|   cogl_material = clutter_texture_get_cogl_material (priv->parent_texture); | ||||
|   if (cogl_material == COGL_INVALID_HANDLE) | ||||
|     return; | ||||
|  | ||||
|   tex_width  = cogl_texture_get_width (cogl_texture); | ||||
|   tex_height = cogl_texture_get_height (cogl_texture); | ||||
|  | ||||
|   clutter_actor_get_allocation_box (self, &box); | ||||
|   width = box.x2 - box.x1; | ||||
|   height = box.y2 - box.y1; | ||||
|  | ||||
|   tx1 = priv->left / tex_width; | ||||
|   tx2 = (tex_width - priv->right) / tex_width; | ||||
|   ty1 = priv->top / tex_height; | ||||
|   ty2 = (tex_height - priv->bottom) / tex_height; | ||||
|  | ||||
|   ex = width - priv->right; | ||||
|   if (ex < 0) | ||||
|     ex = priv->right; 		/* FIXME ? */ | ||||
|  | ||||
|   ey = height - priv->bottom; | ||||
|   if (ey < 0) | ||||
|     ey = priv->bottom; 		/* FIXME ? */ | ||||
|  | ||||
|   opacity = clutter_actor_get_paint_opacity (self); | ||||
|  | ||||
|   /* Paint using the parent texture's material. It should already have | ||||
|      the cogl texture set as the first layer */ | ||||
|   /* NB: for correct blending we need set a preumultiplied color here: */ | ||||
|   cogl_material_set_color4ub (cogl_material, | ||||
|                               opacity, opacity, opacity, opacity); | ||||
|   cogl_set_source (cogl_material); | ||||
|  | ||||
|   { | ||||
|     GLfloat rectangles[] = | ||||
|       { | ||||
|         /* top left corner */ | ||||
|         0, 0, priv->left, priv->top, | ||||
|         0.0, 0.0, | ||||
|         tx1, ty1, | ||||
|  | ||||
|         /* top middle */ | ||||
|         priv->left, 0, ex, priv->top, | ||||
|         tx1, 0.0, | ||||
|         tx2, ty1, | ||||
|  | ||||
|         /* top right */ | ||||
|         ex, 0, width, priv->top, | ||||
|         tx2, 0.0, | ||||
|         1.0, ty1, | ||||
|  | ||||
|         /* mid left */ | ||||
|         0, priv->top, priv->left, ey, | ||||
|         0.0, ty1, | ||||
|         tx1, ty2, | ||||
|  | ||||
|         /* center */ | ||||
|         priv->left, priv->top, ex, ey, | ||||
|         tx1, ty1, | ||||
|         tx2, ty2, | ||||
|  | ||||
|         /* mid right */ | ||||
|         ex, priv->top, width, ey, | ||||
|         tx2, ty1, | ||||
|         1.0, ty2, | ||||
|  | ||||
|         /* bottom left */ | ||||
|         0, ey, priv->left, height, | ||||
|         0.0, ty2, | ||||
|         tx1, 1.0, | ||||
|  | ||||
|         /* bottom center */ | ||||
|         priv->left, ey, ex, height, | ||||
|         tx1, ty2, | ||||
|         tx2, 1.0, | ||||
|  | ||||
|         /* bottom right */ | ||||
|         ex, ey, width, height, | ||||
|         tx2, ty2, | ||||
|         1.0, 1.0 | ||||
|       }; | ||||
|  | ||||
|     cogl_rectangles_with_texture_coords (rectangles, 9); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| nbtk_texture_frame_set_frame_internal (NbtkTextureFrame *frame, | ||||
|                                        gfloat            top, | ||||
|                                        gfloat            right, | ||||
|                                        gfloat            bottom, | ||||
|                                        gfloat            left) | ||||
| { | ||||
|   NbtkTextureFramePrivate *priv = frame->priv; | ||||
|   GObject *gobject = G_OBJECT (frame); | ||||
|   gboolean changed = FALSE; | ||||
|  | ||||
|   g_object_freeze_notify (gobject); | ||||
|  | ||||
|   if (priv->top != top) | ||||
|     { | ||||
|       priv->top = top; | ||||
|       g_object_notify (gobject, "top"); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (priv->right != right) | ||||
|     { | ||||
|       priv->right = right; | ||||
|       g_object_notify (gobject, "right"); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (priv->bottom != bottom) | ||||
|     { | ||||
|       priv->bottom = bottom; | ||||
|       g_object_notify (gobject, "bottom"); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (priv->left != left) | ||||
|     { | ||||
|       priv->left = left; | ||||
|       g_object_notify (gobject, "left"); | ||||
|       changed = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (changed && CLUTTER_ACTOR_IS_VISIBLE (frame)) | ||||
|     clutter_actor_queue_redraw (CLUTTER_ACTOR (frame)); | ||||
|  | ||||
|   g_object_thaw_notify (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_frame_set_property (GObject      *gobject, | ||||
|                                  guint         prop_id, | ||||
|                                  const GValue *value, | ||||
|                                  GParamSpec   *pspec) | ||||
| { | ||||
|   NbtkTextureFrame *frame = NBTK_TEXTURE_FRAME (gobject); | ||||
|   NbtkTextureFramePrivate *priv = frame->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_PARENT_TEXTURE: | ||||
|       nbtk_texture_frame_set_parent_texture (frame, | ||||
|                                              g_value_get_object (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TOP: | ||||
|       nbtk_texture_frame_set_frame_internal (frame, | ||||
|                                              g_value_get_float (value), | ||||
|                                              priv->right, | ||||
|                                              priv->bottom, | ||||
|                                              priv->left); | ||||
|       break; | ||||
|  | ||||
|     case PROP_RIGHT: | ||||
|       nbtk_texture_frame_set_frame_internal (frame, | ||||
|                                              priv->top, | ||||
|                                              g_value_get_float (value), | ||||
|                                              priv->bottom, | ||||
|                                              priv->left); | ||||
|       break; | ||||
|  | ||||
|     case PROP_BOTTOM: | ||||
|       nbtk_texture_frame_set_frame_internal (frame, | ||||
|                                              priv->top, | ||||
|                                              priv->right, | ||||
|                                              g_value_get_float (value), | ||||
|                                              priv->left); | ||||
|       break; | ||||
|  | ||||
|     case PROP_LEFT: | ||||
|       nbtk_texture_frame_set_frame_internal (frame, | ||||
|                                              priv->top, | ||||
|                                              priv->right, | ||||
|                                              priv->bottom, | ||||
|                                              g_value_get_float (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_frame_get_property (GObject    *gobject, | ||||
|                                  guint       prop_id, | ||||
|                                  GValue     *value, | ||||
|                                  GParamSpec *pspec) | ||||
| { | ||||
|   NbtkTextureFramePrivate *priv = NBTK_TEXTURE_FRAME (gobject)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_PARENT_TEXTURE: | ||||
|       g_value_set_object (value, priv->parent_texture); | ||||
|       break; | ||||
|  | ||||
|     case PROP_LEFT: | ||||
|       g_value_set_float (value, priv->left); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TOP: | ||||
|       g_value_set_float (value, priv->top); | ||||
|       break; | ||||
|  | ||||
|     case PROP_RIGHT: | ||||
|       g_value_set_float (value, priv->right); | ||||
|       break; | ||||
|  | ||||
|     case PROP_BOTTOM: | ||||
|       g_value_set_float (value, priv->bottom); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_frame_dispose (GObject *gobject) | ||||
| { | ||||
|   NbtkTextureFramePrivate *priv = NBTK_TEXTURE_FRAME (gobject)->priv; | ||||
|  | ||||
|   if (priv->parent_texture) | ||||
|     { | ||||
|       g_object_unref (priv->parent_texture); | ||||
|       priv->parent_texture = NULL; | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (nbtk_texture_frame_parent_class)->dispose (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_frame_class_init (NbtkTextureFrameClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (gobject_class, sizeof (NbtkTextureFramePrivate)); | ||||
|  | ||||
|   actor_class->get_preferred_width = | ||||
|     nbtk_texture_frame_get_preferred_width; | ||||
|   actor_class->get_preferred_height = | ||||
|     nbtk_texture_frame_get_preferred_height; | ||||
|   actor_class->paint = nbtk_texture_frame_paint; | ||||
|  | ||||
|   gobject_class->set_property = nbtk_texture_frame_set_property; | ||||
|   gobject_class->get_property = nbtk_texture_frame_get_property; | ||||
|   gobject_class->dispose = nbtk_texture_frame_dispose; | ||||
|  | ||||
|   pspec = g_param_spec_object ("parent-texture", | ||||
|                                "Parent Texture", | ||||
|                                "The parent ClutterTexture", | ||||
|                                CLUTTER_TYPE_TEXTURE, | ||||
|                                NBTK_PARAM_READWRITE | | ||||
|                                G_PARAM_CONSTRUCT); | ||||
|   g_object_class_install_property (gobject_class, PROP_PARENT_TEXTURE, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_float ("left", | ||||
|                               "Left", | ||||
|                               "Left offset", | ||||
| 			      0, G_MAXFLOAT, | ||||
|                               0, | ||||
|                               NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_LEFT, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_float ("top", | ||||
|                               "Top", | ||||
|                               "Top offset", | ||||
|                               0, G_MAXFLOAT, | ||||
|                               0, | ||||
|                               NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_TOP, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_float ("bottom", | ||||
|                               "Bottom", | ||||
|                               "Bottom offset", | ||||
|                               0, G_MAXFLOAT, | ||||
|                               0, | ||||
|                               NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_BOTTOM, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_float ("right", | ||||
|                               "Right", | ||||
|                               "Right offset", | ||||
|                               0, G_MAXFLOAT, | ||||
|                               0, | ||||
|                               NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_RIGHT, pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_texture_frame_init (NbtkTextureFrame *self) | ||||
| { | ||||
|   NbtkTextureFramePrivate *priv; | ||||
|  | ||||
|   self->priv = priv = NBTK_TEXTURE_FRAME_GET_PRIVATE (self); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_texture_frame_new: | ||||
|  * @texture: a #ClutterTexture or %NULL | ||||
|  * @left: left margin preserving its content | ||||
|  * @top: top margin preserving its content | ||||
|  * @right: right margin preserving its content | ||||
|  * @bottom: bottom margin preserving its content | ||||
|  * | ||||
|  * A #NbtkTextureFrame is a specialized texture that efficiently clones | ||||
|  * an area of the given @texture while keeping preserving portions of the | ||||
|  * same texture. | ||||
|  * | ||||
|  * A #NbtkTextureFrame can be used to make a rectangular texture fit a | ||||
|  * given size without stretching its borders. | ||||
|  * | ||||
|  * Return value: the newly created #NbtkTextureFrame | ||||
|  */ | ||||
| ClutterActor* | ||||
| nbtk_texture_frame_new (ClutterTexture *texture, | ||||
| 			gfloat          top, | ||||
| 			gfloat          right, | ||||
| 			gfloat          bottom, | ||||
| 			gfloat          left) | ||||
| { | ||||
|   g_return_val_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture), NULL); | ||||
|  | ||||
|   return g_object_new (NBTK_TYPE_TEXTURE_FRAME, | ||||
| 		       "parent-texture", texture, | ||||
| 		       "top", top, | ||||
| 		       "right", right, | ||||
| 		       "bottom", bottom, | ||||
| 		       "left", left, | ||||
| 		       NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_texture_frame_get_parent_texture: | ||||
|  * @frame: A #NbtkTextureFrame | ||||
|  * | ||||
|  * Return the texture used by the #NbtkTextureFrame | ||||
|  * | ||||
|  * Returns: (transfer none): a #ClutterTexture owned by the #NbtkTextureFrame | ||||
|  */ | ||||
| ClutterTexture * | ||||
| nbtk_texture_frame_get_parent_texture (NbtkTextureFrame *frame) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_TEXTURE_FRAME (frame), NULL); | ||||
|  | ||||
|   return frame->priv->parent_texture; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_texture_frame_set_parent_texture: | ||||
|  * @frame: A #NbtkTextureFrame | ||||
|  * @texture: A #ClutterTexture | ||||
|  * | ||||
|  * Set the #ClutterTexture used by this #NbtkTextureFrame | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| nbtk_texture_frame_set_parent_texture (NbtkTextureFrame *frame, | ||||
|                                        ClutterTexture   *texture) | ||||
| { | ||||
|   NbtkTextureFramePrivate *priv; | ||||
|   gboolean was_visible; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_TEXTURE_FRAME (frame)); | ||||
|   g_return_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture)); | ||||
|  | ||||
|   priv = frame->priv; | ||||
|  | ||||
|   was_visible = CLUTTER_ACTOR_IS_VISIBLE (frame); | ||||
|  | ||||
|   if (priv->parent_texture == texture) | ||||
|     return; | ||||
|  | ||||
|   if (priv->parent_texture) | ||||
|     { | ||||
|       g_object_unref (priv->parent_texture); | ||||
|       priv->parent_texture = NULL; | ||||
|  | ||||
|       if (was_visible) | ||||
|         clutter_actor_hide (CLUTTER_ACTOR (frame)); | ||||
|     } | ||||
|  | ||||
|   if (texture) | ||||
|     { | ||||
|       priv->parent_texture = g_object_ref_sink (texture); | ||||
|  | ||||
|       if (was_visible && CLUTTER_ACTOR_IS_VISIBLE (priv->parent_texture)) | ||||
|         clutter_actor_show (CLUTTER_ACTOR (frame)); | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_relayout (CLUTTER_ACTOR (frame)); | ||||
|  | ||||
|   g_object_notify (G_OBJECT (frame), "parent-texture"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_texture_frame_set_frame: | ||||
|  * @frame: A #NbtkTextureFrame | ||||
|  * @top: width of the top slice | ||||
|  * @right: width of the right slice | ||||
|  * @bottom: width of the bottom slice | ||||
|  * @left: width of the left slice | ||||
|  * | ||||
|  * Set the slice lines of the specified frame. The slices are calculated as | ||||
|  * widths from the edge of the frame. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| nbtk_texture_frame_set_frame (NbtkTextureFrame *frame, | ||||
|                               gfloat            top, | ||||
|                               gfloat            right, | ||||
|                               gfloat            bottom, | ||||
|                               gfloat            left) | ||||
| { | ||||
|   g_return_if_fail (NBTK_IS_TEXTURE_FRAME (frame)); | ||||
|  | ||||
|   nbtk_texture_frame_set_frame_internal (frame, top, right, bottom, left); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_texture_frame_get_frame: | ||||
|  * @frame: A #NbtkTextureFrame | ||||
|  * @top: width of the top slice | ||||
|  * @right: width of the right slice | ||||
|  * @bottom: width of the bottom slice | ||||
|  * @left: width of the left slice | ||||
|  * | ||||
|  * Retrieve the current slice lines from the specified frame. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| nbtk_texture_frame_get_frame (NbtkTextureFrame *frame, | ||||
|                               gfloat           *top, | ||||
|                               gfloat           *right, | ||||
|                               gfloat           *bottom, | ||||
|                               gfloat           *left) | ||||
| { | ||||
|   NbtkTextureFramePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_TEXTURE_FRAME (frame)); | ||||
|  | ||||
|   priv = frame->priv; | ||||
|  | ||||
|   if (top) | ||||
|     *top = priv->top; | ||||
|  | ||||
|   if (right) | ||||
|     *right = priv->right; | ||||
|  | ||||
|   if (bottom) | ||||
|     *bottom = priv->bottom; | ||||
|  | ||||
|   if (left) | ||||
|     *left = priv->left; | ||||
| } | ||||
							
								
								
									
										92
									
								
								src/nbtk/nbtk-texture-frame.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/nbtk/nbtk-texture-frame.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| /* | ||||
|  * nbtk-texture-frame.h: Expandible texture actor | ||||
|  * | ||||
|  * Copyright 2007, 2008 OpenedHand Ltd | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_TEXTURE_FRAME_H__ | ||||
| #define __NBTK_TEXTURE_FRAME_H__ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_TEXTURE_FRAME                 (nbtk_texture_frame_get_type ()) | ||||
| #define NBTK_TEXTURE_FRAME(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_TEXTURE_FRAME, NbtkTextureFrame)) | ||||
| #define NBTK_TEXTURE_FRAME_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_TEXTURE_FRAME, NbtkTextureFrameClass)) | ||||
| #define NBTK_IS_TEXTURE_FRAME(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_TEXTURE_FRAME)) | ||||
| #define NBTK_IS_TEXTURE_FRAME_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_TEXTURE_FRAME)) | ||||
| #define NBTK_TEXTURE_FRAME_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_TEXTURE_FRAME, NbtkTextureFrameClass)) | ||||
|  | ||||
| typedef struct _NbtkTextureFrame                NbtkTextureFrame; | ||||
| typedef struct _NbtkTextureFramePrivate         NbtkTextureFramePrivate; | ||||
| typedef struct _NbtkTextureFrameClass           NbtkTextureFrameClass; | ||||
|  | ||||
| /** | ||||
|  * NbtkTextureFrame: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _NbtkTextureFrame | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActor parent_instance; | ||||
|  | ||||
|   NbtkTextureFramePrivate    *priv; | ||||
| }; | ||||
|  | ||||
| struct _NbtkTextureFrameClass | ||||
| { | ||||
|   ClutterActorClass parent_class; | ||||
|  | ||||
|   /* padding for future expansion */ | ||||
|   void (*_clutter_box_1) (void); | ||||
|   void (*_clutter_box_2) (void); | ||||
|   void (*_clutter_box_3) (void); | ||||
|   void (*_clutter_box_4) (void); | ||||
| }; | ||||
|  | ||||
| GType           nbtk_texture_frame_get_type           (void) G_GNUC_CONST; | ||||
| ClutterActor *  nbtk_texture_frame_new                (ClutterTexture   *texture, | ||||
|                                                        gfloat            top, | ||||
|                                                        gfloat            right, | ||||
|                                                        gfloat            bottom, | ||||
|                                                        gfloat            left); | ||||
| void            nbtk_texture_frame_set_parent_texture (NbtkTextureFrame *frame, | ||||
|                                                        ClutterTexture   *texture); | ||||
| ClutterTexture *nbtk_texture_frame_get_parent_texture (NbtkTextureFrame *frame); | ||||
| void            nbtk_texture_frame_set_frame          (NbtkTextureFrame *frame, | ||||
|                                                        gfloat            top, | ||||
|                                                        gfloat            right, | ||||
|                                                        gfloat            bottom, | ||||
|                                                        gfloat            left); | ||||
| void            nbtk_texture_frame_get_frame          (NbtkTextureFrame *frame, | ||||
|                                                        gfloat           *top, | ||||
|                                                        gfloat           *right, | ||||
|                                                        gfloat           *bottom, | ||||
|                                                        gfloat           *left); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_TEXTURE_FRAME_H__ */ | ||||
							
								
								
									
										664
									
								
								src/nbtk/nbtk-tooltip.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										664
									
								
								src/nbtk/nbtk-tooltip.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,664 @@ | ||||
| /* | ||||
|  * nbtk-tooltip.c: Plain tooltip actor | ||||
|  * | ||||
|  * Copyright 2008, 2009 Intel Corporation | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: Thomas Wood <thomas@linux.intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:nbtk-tooltip | ||||
|  * @short_description: A tooltip widget | ||||
|  * | ||||
|  * #NbtkTooltip implements a single tooltip. It should not normally be created | ||||
|  * by the application but by the widget implementing tooltip capabilities, for | ||||
|  * example, #nbtk_button_set_tooltip(). | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include <glib.h> | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "nbtk-tooltip.h" | ||||
|  | ||||
| #include "nbtk-widget.h" | ||||
| #include "nbtk-private.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_LABEL, | ||||
|   PROP_TIP_AREA | ||||
| }; | ||||
|  | ||||
| #define NBTK_TOOLTIP_GET_PRIVATE(obj)    \ | ||||
|         (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_TOOLTIP, NbtkTooltipPrivate)) | ||||
|  | ||||
| struct _NbtkTooltipPrivate | ||||
| { | ||||
|   ClutterActor *label; | ||||
|  | ||||
|   gfloat        arrow_offset; | ||||
|   gboolean      actor_below; | ||||
|  | ||||
|   ClutterGeometry *tip_area; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (NbtkTooltip, nbtk_tooltip, NBTK_TYPE_WIDGET); | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_set_property (GObject      *gobject, | ||||
|                            guint         prop_id, | ||||
|                            const GValue *value, | ||||
|                            GParamSpec   *pspec) | ||||
| { | ||||
|   NbtkTooltip *tooltip = NBTK_TOOLTIP (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_LABEL: | ||||
|       nbtk_tooltip_set_label (tooltip, g_value_get_string (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TIP_AREA: | ||||
|       nbtk_tooltip_set_tip_area (tooltip, g_value_get_boxed (value)); | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_get_property (GObject    *gobject, | ||||
|                            guint       prop_id, | ||||
|                            GValue     *value, | ||||
|                            GParamSpec *pspec) | ||||
| { | ||||
|   NbtkTooltipPrivate *priv = NBTK_TOOLTIP (gobject)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_LABEL: | ||||
|       g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->label))); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TIP_AREA: | ||||
|       g_value_set_boxed (value, priv->tip_area); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_style_changed (NbtkWidget *self) | ||||
| { | ||||
|   NbtkTooltipPrivate *priv; | ||||
|   ShellThemeNode *theme_node; | ||||
|   ClutterColor color; | ||||
|   const PangoFontDescription *font; | ||||
|   gchar *font_string; | ||||
|  | ||||
|   priv = NBTK_TOOLTIP (self)->priv; | ||||
|   theme_node = nbtk_widget_get_theme_node (self); | ||||
|  | ||||
|   shell_theme_node_get_foreground_color (theme_node, &color); | ||||
|   clutter_text_set_color (CLUTTER_TEXT (priv->label), &color); | ||||
|  | ||||
|   font = shell_theme_node_get_font (theme_node); | ||||
|   font_string = pango_font_description_to_string (font); | ||||
|   clutter_text_set_font_name (CLUTTER_TEXT (priv->label), font_string); | ||||
|   g_free (font_string); | ||||
|  | ||||
|   NBTK_WIDGET_CLASS (nbtk_tooltip_parent_class)->style_changed (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_get_preferred_width (ClutterActor *self, | ||||
|                                   gfloat       for_height, | ||||
|                                   gfloat      *min_width_p, | ||||
|                                   gfloat      *natural_width_p) | ||||
| { | ||||
|   NbtkTooltipPrivate *priv = NBTK_TOOLTIP (self)->priv; | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); | ||||
|   gfloat min_label_w, natural_label_w; | ||||
|   gfloat label_height, arrow_height; | ||||
|   ClutterActor *arrow_image; | ||||
|  | ||||
|   shell_theme_node_adjust_for_height (theme_node, &for_height); | ||||
|  | ||||
|   arrow_image = nbtk_widget_get_background_image (NBTK_WIDGET (self)); | ||||
|   if (arrow_image) | ||||
|     { | ||||
|       clutter_actor_get_preferred_height (arrow_image, | ||||
|                                           -1, | ||||
|                                           NULL, | ||||
|                                           &arrow_height); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       arrow_height = 0; | ||||
|     } | ||||
|  | ||||
|   if (for_height > -1) | ||||
|     { | ||||
|       label_height = for_height - arrow_height; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       label_height = -1; | ||||
|     } | ||||
|  | ||||
|   if (priv->label) | ||||
|     { | ||||
|       clutter_actor_get_preferred_width (priv->label, | ||||
|                                          label_height, | ||||
|                                          &min_label_w, | ||||
|                                          &natural_label_w); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       min_label_w = 0; | ||||
|       natural_label_w = 0; | ||||
|     } | ||||
|  | ||||
|   shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_get_preferred_height (ClutterActor *self, | ||||
|                                    gfloat        for_width, | ||||
|                                    gfloat       *min_height_p, | ||||
|                                    gfloat       *natural_height_p) | ||||
| { | ||||
|   NbtkTooltipPrivate *priv = NBTK_TOOLTIP (self)->priv; | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); | ||||
|   gfloat arrow_height; | ||||
|   gfloat min_label_h, natural_label_h; | ||||
|   ClutterActor *arrow_image; | ||||
|  | ||||
|   shell_theme_node_adjust_for_width (theme_node, &for_width); | ||||
|  | ||||
|   arrow_image = nbtk_widget_get_background_image (NBTK_WIDGET (self)); | ||||
|  | ||||
|   if (arrow_image && !priv->actor_below) | ||||
|     { | ||||
|       clutter_actor_get_preferred_height (arrow_image, | ||||
|                                           -1, | ||||
|                                           NULL, | ||||
|                                           &arrow_height); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       arrow_height = 0; | ||||
|     } | ||||
|  | ||||
|   if (priv->label) | ||||
|     { | ||||
|       clutter_actor_get_preferred_height (priv->label, | ||||
|                                           for_width, | ||||
|                                           &min_label_h, | ||||
|                                           &natural_label_h); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       min_label_h = 0; | ||||
|       natural_label_h = 0; | ||||
|     } | ||||
|  | ||||
|   if (min_height_p) | ||||
|     *min_height_p = arrow_height + min_label_h; | ||||
|  | ||||
|   if (natural_height_p) | ||||
|     *natural_height_p = arrow_height + natural_label_h; | ||||
|  | ||||
|   shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_allocate (ClutterActor          *self, | ||||
|                        const ClutterActorBox *box, | ||||
|                        ClutterAllocationFlags flags) | ||||
| { | ||||
|   NbtkTooltipPrivate *priv = NBTK_TOOLTIP (self)->priv; | ||||
|   ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); | ||||
|   ClutterActorBox content_box, child_box, arrow_box; | ||||
|   gfloat arrow_height, arrow_width; | ||||
|   ClutterActor *border_image, *arrow_image; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_tooltip_parent_class)->allocate (self, | ||||
|                                                              box, | ||||
|                                                              flags); | ||||
|  | ||||
|   shell_theme_node_get_content_box (theme_node, box, &content_box); | ||||
|  | ||||
|   arrow_image = nbtk_widget_get_background_image (NBTK_WIDGET (self)); | ||||
|  | ||||
|   if (arrow_image && !priv->actor_below) | ||||
|     { | ||||
|       clutter_actor_get_preferred_height (arrow_image, -1, NULL, &arrow_height); | ||||
|       clutter_actor_get_preferred_width (arrow_image, -1, NULL, &arrow_width); | ||||
|  | ||||
|       arrow_box.x1 = (float) (priv->arrow_offset) - (int) (arrow_width / 2); | ||||
|       arrow_box.y1 = 0; | ||||
|       arrow_box.x2 = arrow_box.x1 + arrow_width; | ||||
|       arrow_box.y2 = arrow_box.y1 + arrow_height; | ||||
|  | ||||
|       clutter_actor_allocate (arrow_image, &arrow_box, flags); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       arrow_height = 0; | ||||
|       arrow_width = 0; | ||||
|     } | ||||
|  | ||||
|   child_box.x1 = child_box.y1 = 0; | ||||
|   child_box.x2 = (box->x2 - box->x1); | ||||
|   child_box.y2 = (box->y2 - box->y1); | ||||
|  | ||||
|   /* remove the space that is used by the arrow */ | ||||
|   child_box.y1 += arrow_height; | ||||
|  | ||||
|   border_image = nbtk_widget_get_border_image (NBTK_WIDGET (self)); | ||||
|   if (border_image) | ||||
|     clutter_actor_allocate (border_image, &child_box, flags); | ||||
|  | ||||
|   if (priv->label) | ||||
|     { | ||||
|       child_box = content_box; | ||||
|       child_box.y1 += arrow_height; | ||||
|  | ||||
|       clutter_actor_allocate (priv->label, &child_box, flags); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_paint (ClutterActor *self) | ||||
| { | ||||
|   ClutterActor *border_image, *arrow_image; | ||||
|   NbtkTooltipPrivate *priv = NBTK_TOOLTIP (self)->priv; | ||||
|  | ||||
|   border_image = nbtk_widget_get_border_image (NBTK_WIDGET (self)); | ||||
|   if (border_image) | ||||
|     clutter_actor_paint (border_image); | ||||
|  | ||||
|   arrow_image = nbtk_widget_get_background_image (NBTK_WIDGET (self)); | ||||
|   if (arrow_image && !priv->actor_below) | ||||
|     clutter_actor_paint (arrow_image); | ||||
|  | ||||
|   clutter_actor_paint (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_map (ClutterActor *self) | ||||
| { | ||||
|   NbtkTooltipPrivate *priv = NBTK_TOOLTIP (self)->priv; | ||||
|   ClutterActor *border_image, *arrow_image; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_tooltip_parent_class)->map (self); | ||||
|  | ||||
|   border_image = nbtk_widget_get_border_image (NBTK_WIDGET (self)); | ||||
|   if (border_image) | ||||
|     clutter_actor_map (border_image); | ||||
|  | ||||
|   arrow_image = nbtk_widget_get_background_image (NBTK_WIDGET (self)); | ||||
|   if (arrow_image) | ||||
|     clutter_actor_map (arrow_image); | ||||
|  | ||||
|   clutter_actor_map (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_unmap (ClutterActor *self) | ||||
| { | ||||
|   NbtkTooltipPrivate *priv = NBTK_TOOLTIP (self)->priv; | ||||
|   ClutterActor *border_image, *arrow_image; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_tooltip_parent_class)->unmap (self); | ||||
|  | ||||
|   border_image = nbtk_widget_get_border_image (NBTK_WIDGET (self)); | ||||
|   if (border_image) | ||||
|     clutter_actor_unmap (border_image); | ||||
|  | ||||
|   arrow_image = nbtk_widget_get_background_image (NBTK_WIDGET (self)); | ||||
|   if (arrow_image) | ||||
|     clutter_actor_unmap (arrow_image); | ||||
|  | ||||
|   clutter_actor_unmap (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_class_init (NbtkTooltipClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (NbtkTooltipPrivate)); | ||||
|  | ||||
|   gobject_class->set_property = nbtk_tooltip_set_property; | ||||
|   gobject_class->get_property = nbtk_tooltip_get_property; | ||||
|  | ||||
|   actor_class->get_preferred_width = nbtk_tooltip_get_preferred_width; | ||||
|   actor_class->get_preferred_height = nbtk_tooltip_get_preferred_height; | ||||
|   actor_class->allocate = nbtk_tooltip_allocate; | ||||
|   actor_class->paint = nbtk_tooltip_paint; | ||||
|   actor_class->map = nbtk_tooltip_map; | ||||
|   actor_class->unmap = nbtk_tooltip_unmap; | ||||
|  | ||||
|   widget_class->style_changed = nbtk_tooltip_style_changed; | ||||
|  | ||||
|   pspec = g_param_spec_string ("label", | ||||
|                                "Label", | ||||
|                                "Label of the tooltip", | ||||
|                                NULL, G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_LABEL, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_boxed ("tip-area", | ||||
|                               "Tip Area", | ||||
|                               "Area on the stage the tooltip applies to", | ||||
|                               CLUTTER_TYPE_GEOMETRY, | ||||
|                               NBTK_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_TIP_AREA, pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_init (NbtkTooltip *tooltip) | ||||
| { | ||||
|   tooltip->priv = NBTK_TOOLTIP_GET_PRIVATE (tooltip); | ||||
|  | ||||
|   tooltip->priv->label = g_object_new (CLUTTER_TYPE_TEXT, | ||||
|                                        "line-alignment", PANGO_ALIGN_CENTER, | ||||
|                                        "ellipsize", PANGO_ELLIPSIZE_END, | ||||
|                                        "use-markup", TRUE, | ||||
|                                        NULL); | ||||
|  | ||||
|   tooltip->priv->tip_area = NULL; | ||||
|  | ||||
|   clutter_actor_set_parent (CLUTTER_ACTOR (tooltip->priv->label), | ||||
|                             CLUTTER_ACTOR (tooltip)); | ||||
|  | ||||
|   g_object_set (tooltip, "show-on-set-parent", FALSE, NULL); | ||||
|  | ||||
|   clutter_actor_set_reactive (CLUTTER_ACTOR (tooltip), FALSE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_update_position (NbtkTooltip *tooltip) | ||||
| { | ||||
|   NbtkTooltipPrivate *priv = tooltip->priv; | ||||
|   ClutterGeometry *tip_area = tooltip->priv->tip_area; | ||||
|   gfloat tooltip_w, tooltip_h, tooltip_x, tooltip_y; | ||||
|   gfloat stage_w, stage_h; | ||||
|   ClutterActor *stage; | ||||
|  | ||||
|   /* ensure the tooltip with is not fixed size */ | ||||
|   clutter_actor_set_size ((ClutterActor*) tooltip, -1, -1); | ||||
|  | ||||
|   /* if no area set, just position ourselves top left */ | ||||
|   if (!priv->tip_area) | ||||
|     { | ||||
|       clutter_actor_set_position ((ClutterActor*) tooltip, 0, 0); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   /* we need to have a style in case there are padding/border values to take into | ||||
|    * account when calculating width/height */ | ||||
|   nbtk_widget_ensure_style ((NbtkWidget *) tooltip); | ||||
|  | ||||
|   /* find out the tooltip's size */ | ||||
|   clutter_actor_get_size ((ClutterActor*) tooltip, &tooltip_w, &tooltip_h); | ||||
|  | ||||
|   /* attempt to place the tooltip */ | ||||
|   tooltip_x = (int) (tip_area->x + (tip_area->width / 2) - (tooltip_w / 2)); | ||||
|   tooltip_y = (int) (tip_area->y + tip_area->height); | ||||
|  | ||||
|   stage = clutter_actor_get_stage ((ClutterActor *) tooltip); | ||||
|   if (!stage) | ||||
|     { | ||||
|       return; | ||||
|     } | ||||
|   clutter_actor_get_size (stage, &stage_w, &stage_h); | ||||
|  | ||||
|   /* make sure the tooltip is not off screen vertically */ | ||||
|   if (tooltip_w > stage_w) | ||||
|     { | ||||
|       tooltip_x = 0; | ||||
|       clutter_actor_set_width ((ClutterActor*) tooltip, stage_w); | ||||
|     } | ||||
|   else if (tooltip_x < 0) | ||||
|     { | ||||
|       tooltip_x = 0; | ||||
|     } | ||||
|   else if (tooltip_x + tooltip_w > stage_w) | ||||
|     { | ||||
|       tooltip_x = (int) (stage_w) - tooltip_w; | ||||
|     } | ||||
|  | ||||
|   /* make sure the tooltip is not off screen horizontally */ | ||||
|   if (tooltip_y + tooltip_h > stage_h) | ||||
|     { | ||||
|       priv->actor_below = TRUE; | ||||
|  | ||||
|       /* re-query size as may have changed */ | ||||
|       clutter_actor_get_preferred_height ((ClutterActor*) tooltip, | ||||
|                                           -1, NULL, &tooltip_h); | ||||
|       tooltip_y = tip_area->y - tooltip_h; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       priv->actor_below = FALSE; | ||||
|     } | ||||
|  | ||||
|   /* calculate the arrow offset */ | ||||
|   priv->arrow_offset = tip_area->x + tip_area->width / 2 - tooltip_x; | ||||
|  | ||||
|   clutter_actor_set_position ((ClutterActor*) tooltip, tooltip_x, tooltip_y); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_tooltip_get_label: | ||||
|  * @tooltip: a #NbtkTooltip | ||||
|  * | ||||
|  * Get the text displayed on the tooltip | ||||
|  * | ||||
|  * Returns: the text for the tooltip. This must not be freed by the application | ||||
|  */ | ||||
| G_CONST_RETURN gchar * | ||||
| nbtk_tooltip_get_label (NbtkTooltip *tooltip) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_TOOLTIP (tooltip), NULL); | ||||
|  | ||||
|   return clutter_text_get_text (CLUTTER_TEXT (tooltip->priv->label)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_tooltip_set_label: | ||||
|  * @tooltip: a #NbtkTooltip | ||||
|  * @text: text to set the label to | ||||
|  * | ||||
|  * Sets the text displayed on the tooltip | ||||
|  */ | ||||
| void | ||||
| nbtk_tooltip_set_label (NbtkTooltip *tooltip, | ||||
|                         const gchar *text) | ||||
| { | ||||
|   NbtkTooltipPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (NBTK_IS_TOOLTIP (tooltip)); | ||||
|  | ||||
|   priv = tooltip->priv; | ||||
|  | ||||
|   clutter_text_set_text (CLUTTER_TEXT (priv->label), text); | ||||
|  | ||||
|   g_object_notify (G_OBJECT (tooltip), "label"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_tooltip_show: | ||||
|  * @tooltip: a #NbtkTooltip | ||||
|  * | ||||
|  * Show the tooltip relative to the associated widget. | ||||
|  */ | ||||
| void | ||||
| nbtk_tooltip_show (NbtkTooltip *tooltip) | ||||
| { | ||||
|   NbtkTooltipPrivate *priv; | ||||
|   ClutterActor *parent; | ||||
|   ClutterActor *stage; | ||||
|   ClutterActor *self = CLUTTER_ACTOR (tooltip); | ||||
|   ClutterAnimation *animation; | ||||
|  | ||||
|   /* make sure we're not currently already animating (e.g. hiding) */ | ||||
|   animation = clutter_actor_get_animation (CLUTTER_ACTOR (tooltip)); | ||||
|   if (animation) | ||||
|     clutter_animation_completed (animation); | ||||
|  | ||||
|   priv = tooltip->priv; | ||||
|   parent = clutter_actor_get_parent (self); | ||||
|   stage = clutter_actor_get_stage (self); | ||||
|  | ||||
|   if (!stage) | ||||
|     { | ||||
|       g_warning ("NbtkTooltip is not on any stage."); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   /* make sure we're parented on the stage */ | ||||
|   if (G_UNLIKELY (parent != stage)) | ||||
|     { | ||||
|       g_object_ref (self); | ||||
|       clutter_actor_unparent (self); | ||||
|       clutter_actor_set_parent (self, stage); | ||||
|       g_object_unref (self); | ||||
|       parent = stage; | ||||
|     } | ||||
|  | ||||
|   /* raise the tooltip to the top */ | ||||
|   clutter_container_raise_child (CLUTTER_CONTAINER (stage), | ||||
|                                  CLUTTER_ACTOR (tooltip), | ||||
|                                  NULL); | ||||
|  | ||||
|   nbtk_tooltip_update_position (tooltip); | ||||
|  | ||||
|   /* finally show the tooltip... */ | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_tooltip_parent_class)->show (self); | ||||
|  | ||||
|   /* and give it some bounce! */ | ||||
|   g_object_set (G_OBJECT (self), | ||||
|                 "scale-center-x", priv->arrow_offset, | ||||
|                 "scale-center-y", (priv->actor_below) ? clutter_actor_get_height (self) : 0, | ||||
|                 NULL); | ||||
|   clutter_actor_set_scale (self, 0.0, 0.0); | ||||
|   clutter_actor_animate (self, CLUTTER_EASE_OUT_ELASTIC, | ||||
|                          500, | ||||
|                          "scale-x", 1.0, | ||||
|                          "scale-y", 1.0, | ||||
|                          NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| nbtk_tooltip_hide_complete (ClutterAnimation *animation, | ||||
|                             ClutterActor     *actor) | ||||
| { | ||||
|   CLUTTER_ACTOR_CLASS (nbtk_tooltip_parent_class)->hide (actor); | ||||
|   g_signal_handlers_disconnect_by_func (actor, | ||||
|                                         nbtk_tooltip_hide_complete, | ||||
|                                         actor); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_tooltip_hide: | ||||
|  * @tooltip: a #NbtkTooltip | ||||
|  * | ||||
|  * Hide the tooltip | ||||
|  */ | ||||
| void | ||||
| nbtk_tooltip_hide (NbtkTooltip *tooltip) | ||||
| { | ||||
|   ClutterAnimation *animation; | ||||
|  | ||||
|   g_return_if_fail (NBTK_TOOLTIP (tooltip)); | ||||
|  | ||||
|   /* make sure we're not currently already animating (e.g. hiding) */ | ||||
|   animation = clutter_actor_get_animation (CLUTTER_ACTOR (tooltip)); | ||||
|   if (animation) | ||||
|     clutter_animation_completed (animation); | ||||
|  | ||||
|   g_object_set (G_OBJECT (tooltip), | ||||
|                 "scale-center-x", tooltip->priv->arrow_offset, | ||||
|                 NULL); | ||||
|   animation = | ||||
|     clutter_actor_animate (CLUTTER_ACTOR (tooltip), CLUTTER_EASE_IN_SINE, | ||||
|                            150, | ||||
|                            "scale-x", 0.0, | ||||
|                            "scale-y", 0.0, | ||||
|                            NULL); | ||||
|   g_signal_connect (animation, "completed", | ||||
|                     G_CALLBACK (nbtk_tooltip_hide_complete), tooltip); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_tooltip_set_tip_area: | ||||
|  * @tooltip: A #NbtkTooltip | ||||
|  * @area: A #ClutterGeometry | ||||
|  * | ||||
|  * Set the area on the stage that the tooltip applies to. | ||||
|  */ | ||||
| void | ||||
| nbtk_tooltip_set_tip_area (NbtkTooltip           *tooltip, | ||||
|                            const ClutterGeometry *area) | ||||
| { | ||||
|   g_return_if_fail (NBTK_IS_TOOLTIP (tooltip)); | ||||
|  | ||||
|   if (tooltip->priv->tip_area) | ||||
|     g_boxed_free (CLUTTER_TYPE_GEOMETRY, tooltip->priv->tip_area); | ||||
|   tooltip->priv->tip_area = g_boxed_copy (CLUTTER_TYPE_GEOMETRY, area); | ||||
|  | ||||
|   nbtk_tooltip_update_position (tooltip); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * nbtk_tooltip_get_tip_area: | ||||
|  * @tooltip: A #NbtkTooltip | ||||
|  * | ||||
|  * Retrieve the area on the stage that the tooltip currently applies to | ||||
|  * | ||||
|  * Returns: the #ClutterGeometry, owned by the tooltip which must not be freed | ||||
|  * by the application. | ||||
|  */ | ||||
| G_CONST_RETURN ClutterGeometry* | ||||
| nbtk_tooltip_get_tip_area (NbtkTooltip *tooltip) | ||||
| { | ||||
|   g_return_val_if_fail (NBTK_IS_TOOLTIP (tooltip), NULL); | ||||
|  | ||||
|   return tooltip->priv->tip_area; | ||||
| } | ||||
							
								
								
									
										79
									
								
								src/nbtk/nbtk-tooltip.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/nbtk/nbtk-tooltip.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| /* | ||||
|  * nbtk-tooltip.h: Plain tooltip actor | ||||
|  * | ||||
|  * Copyright 2008, 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: Thomas Wood <thomas@linux.intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_TOOLTIP_H__ | ||||
| #define __NBTK_TOOLTIP_H__ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #include <nbtk/nbtk-bin.h> | ||||
|  | ||||
| #define NBTK_TYPE_TOOLTIP                (nbtk_tooltip_get_type ()) | ||||
| #define NBTK_TOOLTIP(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_TOOLTIP, NbtkTooltip)) | ||||
| #define NBTK_IS_TOOLTIP(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_TOOLTIP)) | ||||
| #define NBTK_TOOLTIP_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_TOOLTIP, NbtkTooltipClass)) | ||||
| #define NBTK_IS_TOOLTIP_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_TOOLTIP)) | ||||
| #define NBTK_TOOLTIP_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_TOOLTIP, NbtkTooltipClass)) | ||||
|  | ||||
| typedef struct _NbtkTooltip              NbtkTooltip; | ||||
| typedef struct _NbtkTooltipPrivate       NbtkTooltipPrivate; | ||||
| typedef struct _NbtkTooltipClass         NbtkTooltipClass; | ||||
|  | ||||
| /** | ||||
|  * NbtkTooltip: | ||||
|  * | ||||
|  * The contents of this structure is private and should only be accessed using | ||||
|  * the provided API. | ||||
|  */ | ||||
| struct _NbtkTooltip | ||||
| { | ||||
|   /*< private >*/ | ||||
|   NbtkBin parent_instance; | ||||
|  | ||||
|   NbtkTooltipPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _NbtkTooltipClass | ||||
| { | ||||
|   NbtkBinClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType nbtk_tooltip_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| G_CONST_RETURN gchar *nbtk_tooltip_get_label (NbtkTooltip *tooltip); | ||||
| void                  nbtk_tooltip_set_label (NbtkTooltip *tooltip, | ||||
|                                               const gchar *text); | ||||
| void                  nbtk_tooltip_show      (NbtkTooltip *tooltip); | ||||
| void                  nbtk_tooltip_hide      (NbtkTooltip *tooltip); | ||||
|  | ||||
| void                  nbtk_tooltip_set_tip_area (NbtkTooltip *tooltip, const ClutterGeometry *area); | ||||
| G_CONST_RETURN ClutterGeometry* nbtk_tooltip_get_tip_area (NbtkTooltip *tooltip); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_TOOLTIP_H__ */ | ||||
							
								
								
									
										59
									
								
								src/nbtk/nbtk-types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/nbtk/nbtk-types.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| /* | ||||
|  * Copyright 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_TYPES_H__ | ||||
| #define __NBTK_TYPES_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_PADDING               (nbtk_padding_get_type ()) | ||||
|  | ||||
| /** | ||||
|  * NbtkAlignment: | ||||
|  * @NBTK_ALIGN_TOP: align to the top (vertically) | ||||
|  * @NBTK_ALIGN_RIGHT: align to the right (horizontally) | ||||
|  * @NBTK_ALIGN_BOTTOM: align to the bottom (vertically) | ||||
|  * @NBTK_ALIGN_LEFT: align to the left (horizontally) | ||||
|  * @NBTK_ALIGN_CENTER: align to the center (horizontally or vertically) | ||||
|  * | ||||
|  * The alignment values for a #NbtkBin. | ||||
|  */ | ||||
| typedef enum { | ||||
|   NBTK_ALIGN_TOP, | ||||
|   NBTK_ALIGN_RIGHT, | ||||
|   NBTK_ALIGN_BOTTOM, | ||||
|   NBTK_ALIGN_LEFT, | ||||
|   NBTK_ALIGN_CENTER | ||||
| } NbtkAlignment; | ||||
|  | ||||
| typedef enum { | ||||
|   NBTK_ALIGN_START, | ||||
|   NBTK_ALIGN_MIDDLE, | ||||
|   NBTK_ALIGN_END | ||||
| } NbtkAlign; | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_TYPES_H__ */ | ||||
							
								
								
									
										1378
									
								
								src/nbtk/nbtk-widget.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1378
									
								
								src/nbtk/nbtk-widget.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										116
									
								
								src/nbtk/nbtk-widget.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/nbtk/nbtk-widget.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| /* | ||||
|  * nbtk-widget.h: Base class for Nbtk actors | ||||
|  * | ||||
|  * Copyright 2007 OpenedHand | ||||
|  * Copyright 2008, 2009 Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU Lesser General Public License, | ||||
|  * version 2.1, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT ANY | ||||
|  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION) | ||||
| #error "Only <nbtk/nbtk.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __NBTK_WIDGET_H__ | ||||
| #define __NBTK_WIDGET_H__ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <nbtk/nbtk-types.h> | ||||
| #include <toolkit/shell-theme.h> | ||||
| #include <toolkit/shell-theme-node.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define NBTK_TYPE_WIDGET                 (nbtk_widget_get_type ()) | ||||
| #define NBTK_WIDGET(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_WIDGET, NbtkWidget)) | ||||
| #define NBTK_IS_WIDGET(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_WIDGET)) | ||||
| #define NBTK_WIDGET_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_WIDGET, NbtkWidgetClass)) | ||||
| #define NBTK_IS_WIDGET_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_WIDGET)) | ||||
| #define NBTK_WIDGET_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_WIDGET, NbtkWidgetClass)) | ||||
|  | ||||
| typedef struct _NbtkWidget               NbtkWidget; | ||||
| typedef struct _NbtkWidgetPrivate        NbtkWidgetPrivate; | ||||
| typedef struct _NbtkWidgetClass          NbtkWidgetClass; | ||||
|  | ||||
| /** | ||||
|  * NbtkWidget: | ||||
|  * | ||||
|  * Base class for stylable actors. The contents of the #NbtkWidget | ||||
|  * structure are private and should only be accessed through the | ||||
|  * public API. | ||||
|  */ | ||||
| struct _NbtkWidget | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActor parent_instance; | ||||
|  | ||||
|   NbtkWidgetPrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * NbtkWidgetClass: | ||||
|  * | ||||
|  * Base class for stylable actors. | ||||
|  */ | ||||
| struct _NbtkWidgetClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActorClass parent_class; | ||||
|  | ||||
|   /* vfuncs */ | ||||
|   void (* draw_background) (NbtkWidget         *self); | ||||
|   void (* style_changed)   (NbtkWidget         *self); | ||||
| }; | ||||
|  | ||||
| GType nbtk_widget_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| void                  nbtk_widget_set_style_pseudo_class (NbtkWidget   *actor, | ||||
|                                                           const gchar  *pseudo_class); | ||||
| G_CONST_RETURN gchar *nbtk_widget_get_style_pseudo_class (NbtkWidget   *actor); | ||||
| void                  nbtk_widget_set_style_class_name   (NbtkWidget   *actor, | ||||
|                                                           const gchar  *style_class); | ||||
| G_CONST_RETURN gchar *nbtk_widget_get_style_class_name   (NbtkWidget   *actor); | ||||
| void                  nbtk_widget_set_style              (NbtkWidget   *actor, | ||||
| 							  const gchar  *style); | ||||
| G_CONST_RETURN gchar *nbtk_widget_get_style              (NbtkWidget   *actor); | ||||
|  | ||||
| void        nbtk_widget_set_theme (NbtkWidget *actor, | ||||
| 				   ShellTheme *theme); | ||||
| ShellTheme *nbtk_widget_get_theme (NbtkWidget *actor); | ||||
|  | ||||
| void     nbtk_widget_set_has_tooltip (NbtkWidget *widget, gboolean has_tooltip); | ||||
| gboolean nbtk_widget_get_has_tooltip (NbtkWidget *widget); | ||||
| void     nbtk_widget_set_tooltip_text (NbtkWidget *widget, const gchar *text); | ||||
| const gchar* nbtk_widget_get_tooltip_text (NbtkWidget *widget); | ||||
|  | ||||
| void nbtk_widget_show_tooltip (NbtkWidget *widget); | ||||
| void nbtk_widget_hide_tooltip (NbtkWidget *widget); | ||||
|  | ||||
| void nbtk_widget_ensure_style (NbtkWidget *widget); | ||||
|  | ||||
|  | ||||
| /* Only to be used by sub-classes of NbtkWidget */ | ||||
| void          nbtk_widget_style_changed        (NbtkWidget  *widget); | ||||
|  | ||||
| ShellThemeNode *nbtk_widget_get_theme_node     (NbtkWidget  *widget); | ||||
|  | ||||
| ClutterActor *nbtk_widget_get_background_image (NbtkWidget  *actor); | ||||
| ClutterActor *nbtk_widget_get_border_image     (NbtkWidget  *actor); | ||||
| void          nbtk_widget_draw_background      (NbtkWidget  *widget); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __NBTK_WIDGET_H__ */ | ||||
| @@ -40,6 +40,7 @@ struct _ShellGlobal { | ||||
|    | ||||
|   MutterPlugin *plugin; | ||||
|   ShellWM *wm; | ||||
|   const char *datadir; | ||||
|   const char *imagedir; | ||||
|   const char *configdir; | ||||
|  | ||||
| @@ -57,6 +58,7 @@ enum { | ||||
|   PROP_STAGE, | ||||
|   PROP_WINDOW_GROUP, | ||||
|   PROP_WINDOW_MANAGER, | ||||
|   PROP_DATADIR, | ||||
|   PROP_IMAGEDIR, | ||||
|   PROP_CONFIGDIR, | ||||
| }; | ||||
| @@ -128,6 +130,9 @@ shell_global_get_property(GObject         *object, | ||||
|     case PROP_WINDOW_MANAGER: | ||||
|       g_value_set_object (value, global->wm); | ||||
|       break; | ||||
|     case PROP_DATADIR: | ||||
|       g_value_set_string (value, global->datadir); | ||||
|       break; | ||||
|     case PROP_IMAGEDIR: | ||||
|       g_value_set_string (value, global->imagedir); | ||||
|       break; | ||||
| @@ -149,6 +154,7 @@ shell_global_init (ShellGlobal *global) | ||||
|  | ||||
|   if (!datadir) | ||||
|     datadir = GNOME_SHELL_DATADIR; | ||||
|   global->datadir = datadir; | ||||
|  | ||||
|   /* We make sure imagedir ends with a '/', since the JS won't have | ||||
|    * access to g_build_filename() and so will end up just | ||||
| @@ -254,6 +260,13 @@ shell_global_class_init (ShellGlobalClass *klass) | ||||
|                                                         "Window management interface", | ||||
|                                                         SHELL_TYPE_WM, | ||||
|                                                         G_PARAM_READABLE)); | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_DATADIR, | ||||
|                                    g_param_spec_string ("datadir", | ||||
|                                                         "Data directory", | ||||
|                                                         "Directory containing gnome-shell data files", | ||||
|                                                         NULL, | ||||
|                                                         G_PARAM_READABLE)); | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_IMAGEDIR, | ||||
|                                    g_param_spec_string ("imagedir", | ||||
|   | ||||
| @@ -1,240 +0,0 @@ | ||||
| #include "shell-panel-window.h" | ||||
|  | ||||
| #include <gdk/gdkx.h> | ||||
| #include <X11/Xlib.h> | ||||
|  | ||||
| #define PANEL_HEIGHT 25 | ||||
|  | ||||
| enum { | ||||
|    PROP_0, | ||||
|  | ||||
| }; | ||||
|  | ||||
| static void shell_panel_window_finalize (GObject *object); | ||||
| static void shell_panel_window_size_request (GtkWidget *self, GtkRequisition *req); | ||||
| static void shell_panel_window_size_allocate (GtkWidget *self, GtkAllocation *allocation); | ||||
| static void shell_panel_window_realize (GtkWidget *self); | ||||
| static void shell_panel_window_show (GtkWidget *self); | ||||
| static void set_strut (ShellPanelWindow *self); | ||||
| static void on_workarea_changed (ShellPanelWindow *self); | ||||
| static void handle_new_workarea (ShellPanelWindow *self); | ||||
| static GdkFilterReturn filter_func (GdkXEvent *xevent, | ||||
| 				    GdkEvent *event, | ||||
| 				    gpointer data); | ||||
|  | ||||
| G_DEFINE_TYPE(ShellPanelWindow, shell_panel_window, GTK_TYPE_WINDOW); | ||||
|  | ||||
| struct ShellPanelWindowPrivate { | ||||
|   GtkAllocation workarea; | ||||
|   guint width; | ||||
|   guint height; | ||||
|   Atom workarea_atom; | ||||
| }; | ||||
|  | ||||
| static void | ||||
| shell_panel_window_class_init(ShellPanelWindowClass *klass) | ||||
| { | ||||
|     GObjectClass *gobject_class = (GObjectClass *)klass; | ||||
|     GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; | ||||
|  | ||||
|     gobject_class->finalize = shell_panel_window_finalize; | ||||
|      | ||||
|     widget_class->realize = shell_panel_window_realize; | ||||
|     widget_class->size_request = shell_panel_window_size_request;     | ||||
|     widget_class->size_allocate = shell_panel_window_size_allocate; | ||||
|     widget_class->show = shell_panel_window_show; | ||||
| } | ||||
|  | ||||
| static void shell_panel_window_init (ShellPanelWindow *self) | ||||
| { | ||||
|   self->priv = g_new0 (ShellPanelWindowPrivate, 1); | ||||
|  | ||||
|   self->priv->workarea_atom = gdk_x11_get_xatom_by_name_for_display (gdk_display_get_default (), "_NET_WORKAREA"); | ||||
|    | ||||
|   gtk_window_set_type_hint (GTK_WINDOW (self), GDK_WINDOW_TYPE_HINT_DOCK); | ||||
|   gtk_window_set_focus_on_map (GTK_WINDOW (self), FALSE); | ||||
|   gdk_window_add_filter (NULL, filter_func, self); | ||||
| } | ||||
|  | ||||
| static void shell_panel_window_finalize (GObject *object) | ||||
| { | ||||
|     ShellPanelWindow *self = (ShellPanelWindow*)object; | ||||
|  | ||||
|     g_free (self->priv); | ||||
|     g_signal_handlers_destroy(object); | ||||
|     G_OBJECT_CLASS (shell_panel_window_parent_class)->finalize(object); | ||||
| } | ||||
|  | ||||
| ShellPanelWindow* shell_panel_window_new(void) { | ||||
|     return (ShellPanelWindow*) g_object_new(SHELL_TYPE_PANEL_WINDOW,  | ||||
|         "type", GTK_WINDOW_TOPLEVEL, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_strut (ShellPanelWindow *self) | ||||
| { | ||||
|   long *buf; | ||||
|   int strut_size; | ||||
|  | ||||
|   strut_size = GTK_WIDGET (self)->allocation.height; | ||||
|  | ||||
|   buf = g_new0 (long, 4); | ||||
|   buf[0] = 0; /* left */ | ||||
|   buf[1] = 0; /* right */ | ||||
|   buf[2] = 0; /* top */ | ||||
|   buf[3] = strut_size; /* bottom */ | ||||
|   gdk_property_change (GTK_WIDGET (self)->window, gdk_atom_intern_static_string ("_NET_WM_STRUT"), | ||||
| 		       gdk_atom_intern_static_string ("CARDINAL"), 32, | ||||
| 		       GDK_PROP_MODE_REPLACE, | ||||
| 		       (guchar*) buf, 4); | ||||
|   g_free (buf); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_panel_window_size_request (GtkWidget *widget, GtkRequisition *requisition) | ||||
| { | ||||
|   ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget);   | ||||
|   GTK_WIDGET_CLASS (shell_panel_window_parent_class)->size_request(widget, requisition);   | ||||
|   requisition->width = self->priv->width; | ||||
|   requisition->height = PANEL_HEIGHT;  | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_panel_window_size_allocate (GtkWidget *widget, GtkAllocation *allocation) | ||||
| { | ||||
|   ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget); | ||||
|   GTK_WIDGET_CLASS (shell_panel_window_parent_class)->size_allocate(widget, allocation); | ||||
|   if (GTK_WIDGET_REALIZED (self)) | ||||
|     set_strut (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_panel_window_realize (GtkWidget *widget) | ||||
| { | ||||
|   ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget); | ||||
|   GTK_WIDGET_CLASS (shell_panel_window_parent_class)->realize(widget); | ||||
|   set_strut (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_panel_window_show (GtkWidget *widget) | ||||
| { | ||||
|   ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget); | ||||
|   on_workarea_changed (self); | ||||
|   GTK_WIDGET_CLASS (shell_panel_window_parent_class)->show(widget); | ||||
| } | ||||
|  | ||||
| static void | ||||
| handle_new_workarea (ShellPanelWindow *self) | ||||
| { | ||||
|   GtkRequisition requisition; | ||||
|   int x, y; | ||||
|   int width; | ||||
|   int height; | ||||
|   int x_target, y_target; | ||||
|  | ||||
|   gtk_widget_size_request (GTK_WIDGET (self), &requisition); | ||||
|  | ||||
|   /* If we don't have a workarea, just use monitor */ | ||||
|   if (self->priv->workarea.width == 0)  | ||||
|     { | ||||
|       int monitor; | ||||
|       GdkRectangle monitor_geometry;       | ||||
|        | ||||
|       monitor = gdk_screen_get_monitor_at_point (gdk_screen_get_default (), | ||||
|                                                  0, 0); | ||||
|       gdk_screen_get_monitor_geometry (gdk_screen_get_default (), | ||||
|                                        monitor, &monitor_geometry);       | ||||
|       x = monitor_geometry.x; | ||||
|       y = monitor_geometry.y; | ||||
|       width = monitor_geometry.width; | ||||
|       height = monitor_geometry.height; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       x = self->priv->workarea.x; | ||||
|       y = self->priv->workarea.y; | ||||
|       width = self->priv->workarea.width; | ||||
|       height = self->priv->workarea.height; | ||||
|     } | ||||
|    | ||||
|   x_target = x; | ||||
|   y_target = y + height - requisition.height; | ||||
|  | ||||
|   self->priv->width = width; | ||||
|   self->priv->height = height; | ||||
|   gtk_widget_set_size_request (GTK_WIDGET (self), width - x_target, PANEL_HEIGHT); | ||||
|   gtk_window_move (GTK_WINDOW (self), x_target, y_target); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_workarea_changed (ShellPanelWindow *self) | ||||
| { | ||||
|   gulong bytes_after, nitems; | ||||
|   Atom type; | ||||
|   gint format; | ||||
|   guchar *data; | ||||
|   long *data32; | ||||
|   Atom workarea = gdk_x11_get_xatom_by_name_for_display (gdk_display_get_default (), "_NET_WORKAREA"); | ||||
|  | ||||
|   XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(), | ||||
| 		      workarea, | ||||
| 		      0, 4, FALSE, workarea, | ||||
| 		      &type, &format, &nitems, &bytes_after, &data); | ||||
|   if ((format == 32) && (nitems == 4) && (bytes_after == 0)) | ||||
|     { | ||||
|       int x, y, width, height; | ||||
|       data32 = (long*) data; | ||||
|       x = data32[0]; | ||||
|       y = data32[1]; | ||||
|       width = data32[2]; | ||||
|       height = data32[3]; | ||||
|       if (x == self->priv->workarea.x && y == self->priv->workarea.y  | ||||
|           && width == self->priv->workarea.width  | ||||
|           && height == self->priv->workarea.height) | ||||
|         return; | ||||
|  | ||||
|       self->priv->workarea.x = x; | ||||
|       self->priv->workarea.y = y; | ||||
|       self->priv->workarea.width = width; | ||||
|       self->priv->workarea.height = height; | ||||
|  | ||||
|       handle_new_workarea (self); | ||||
|     } | ||||
|   else if (nitems == 0) | ||||
|     { | ||||
|       /* We have no workarea set; assume there are no other panels at this time */ | ||||
|       self->priv->workarea.x = self->priv->workarea.y = 0; | ||||
|       self->priv->workarea.width = self->priv->workarea.height = 0; | ||||
|       handle_new_workarea (self); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       g_printerr ("unexpected return from XGetWindowProperty: %d %ld %ld\n", | ||||
|           format, nitems, bytes_after); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static GdkFilterReturn | ||||
| filter_func (GdkXEvent *gdk_xevent, | ||||
| 	     GdkEvent *event, | ||||
| 	     gpointer data) | ||||
| { | ||||
|   ShellPanelWindow *self = SHELL_PANEL_WINDOW (data); | ||||
|   GdkFilterReturn ret = GDK_FILTER_CONTINUE; | ||||
|   XEvent *xevent = (XEvent *) event; | ||||
|  | ||||
|   switch (xevent->type)  | ||||
|   { | ||||
|   case PropertyNotify: | ||||
|     { | ||||
|       if (xevent->xproperty.atom != self->priv->workarea_atom) | ||||
| 	break; | ||||
|       on_workarea_changed (self); | ||||
|     } | ||||
|     break; | ||||
|   default: | ||||
|     break; | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
| @@ -1,35 +0,0 @@ | ||||
| #ifndef __SHELL_PANEL_WINDOW_H__ | ||||
| #define __SHELL_PANEL_WINDOW_H__ | ||||
|  | ||||
| #include <gtk/gtk.h> | ||||
|  | ||||
| #define SHELL_TYPE_PANEL_WINDOW                 (shell_panel_window_get_type ()) | ||||
| #define SHELL_PANEL_WINDOW(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindow)) | ||||
| #define SHELL_PANEL_WINDOW_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindowClass)) | ||||
| #define SHELL_IS_PANEL_WINDOW(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_PANEL_WINDOW)) | ||||
| #define SHELL_IS_PANEL_WINDOW_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_PANEL_WINDOW)) | ||||
| #define SHELL_PANEL_WINDOW_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindowClass)) | ||||
|  | ||||
| typedef struct _ShellPanelWindow ShellPanelWindow; | ||||
| typedef struct _ShellPanelWindowClass ShellPanelWindowClass; | ||||
|  | ||||
| typedef struct ShellPanelWindowPrivate ShellPanelWindowPrivate; | ||||
|  | ||||
| struct _ShellPanelWindow | ||||
| { | ||||
|     GtkWindow parent; | ||||
|  | ||||
|     ShellPanelWindowPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _ShellPanelWindowClass | ||||
| { | ||||
|     GtkWindowClass parent_class; | ||||
|  | ||||
| }; | ||||
|  | ||||
| GType shell_panel_window_get_type (void) G_GNUC_CONST; | ||||
| ShellPanelWindow* shell_panel_window_new(void); | ||||
|  | ||||
|  | ||||
| #endif /* __SHELL_PANEL_WINDOW_H__ */ | ||||
							
								
								
									
										92
									
								
								src/toolkit/shell-border-image.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/toolkit/shell-border-image.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include "shell-border-image.h" | ||||
|  | ||||
| struct _ShellBorderImage { | ||||
|   GObject parent; | ||||
|  | ||||
|   char *filename; | ||||
|   int border_top; | ||||
|   int border_right; | ||||
|   int border_bottom; | ||||
|   int border_left; | ||||
| }; | ||||
|  | ||||
| struct _ShellBorderImageClass { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (ShellBorderImage, shell_border_image, G_TYPE_OBJECT) | ||||
|  | ||||
| static void | ||||
| shell_border_image_finalize (GObject *object) | ||||
| { | ||||
|   ShellBorderImage *image = SHELL_BORDER_IMAGE (object); | ||||
|  | ||||
|   g_free (image->filename); | ||||
|  | ||||
|   G_OBJECT_CLASS (shell_border_image_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_border_image_class_init (ShellBorderImageClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = shell_border_image_finalize; | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_border_image_init (ShellBorderImage *image) | ||||
| { | ||||
| } | ||||
|  | ||||
| ShellBorderImage * | ||||
| shell_border_image_new (const char *filename, | ||||
|                        int         border_top, | ||||
|                        int         border_right, | ||||
|                        int         border_bottom, | ||||
|                        int         border_left) | ||||
| { | ||||
|   ShellBorderImage *image; | ||||
|  | ||||
|   image = g_object_new (SHELL_TYPE_BORDER_IMAGE, NULL); | ||||
|  | ||||
|   image->filename = g_strdup (filename); | ||||
|   image->border_top = border_top; | ||||
|   image->border_right = border_right; | ||||
|   image->border_bottom = border_bottom; | ||||
|   image->border_left = border_left; | ||||
|  | ||||
|   return image; | ||||
| } | ||||
|  | ||||
| const char * | ||||
| shell_border_image_get_filename (ShellBorderImage *image) | ||||
| { | ||||
|   g_return_val_if_fail (SHELL_IS_BORDER_IMAGE (image), NULL); | ||||
|  | ||||
|   return image->filename; | ||||
| } | ||||
|  | ||||
| void | ||||
| shell_border_image_get_borders (ShellBorderImage *image, | ||||
|                                 int              *border_top, | ||||
|                                 int              *border_right, | ||||
|                                 int              *border_bottom, | ||||
|                                 int              *border_left) | ||||
| { | ||||
|   g_return_if_fail (SHELL_IS_BORDER_IMAGE (image)); | ||||
|  | ||||
|   if (border_top) | ||||
|     *border_top = image->border_top; | ||||
|   if (border_right) | ||||
|     *border_right = image->border_right; | ||||
|   if (border_bottom) | ||||
|     *border_bottom = image->border_bottom; | ||||
|   if (border_left) | ||||
|     *border_left = image->border_left; | ||||
| } | ||||
							
								
								
									
										38
									
								
								src/toolkit/shell-border-image.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/toolkit/shell-border-image.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| #ifndef __SHELL_BORDER_IMAGE_H__ | ||||
| #define __SHELL_BORDER_IMAGE_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| /* A ShellBorderImage encapsulates an image with specified unscaled borders on each edge. | ||||
|  */ | ||||
| typedef struct _ShellBorderImage      ShellBorderImage; | ||||
| typedef struct _ShellBorderImageClass ShellBorderImageClass; | ||||
|  | ||||
| #define SHELL_TYPE_BORDER_IMAGE             (shell_border_image_get_type ()) | ||||
| #define SHELL_BORDER_IMAGE(object)          (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_BORDER_IMAGE, ShellBorderImage)) | ||||
| #define SHELL_BORDER_IMAGE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_BORDER_IMAGE, ShellBorderImageClass)) | ||||
| #define SHELL_IS_BORDER_IMAGE(object)       (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_BORDER_IMAGE)) | ||||
| #define SHELL_IS_BORDER_IMAGE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_BORDER_IMAGE)) | ||||
| #define SHELL_BORDER_IMAGE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_BORDER_IMAGE, ShellBorderImageClass)) | ||||
|  | ||||
| GType             shell_border_image_get_type          (void) G_GNUC_CONST; | ||||
|  | ||||
| ShellBorderImage *shell_border_image_new (const char *filename, | ||||
|                                           int         border_top, | ||||
|                                           int         border_right, | ||||
|                                           int         border_bottom, | ||||
|                                           int         border_left); | ||||
|  | ||||
| const char *shell_border_image_get_filename (ShellBorderImage *image); | ||||
| void        shell_border_image_get_borders  (ShellBorderImage *image, | ||||
|                                              int             *border_top, | ||||
|                                              int             *border_right, | ||||
|                                              int             *border_bottom, | ||||
|                                              int             *border_left); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __SHELL_BORDER_IMAGE_H__ */ | ||||
							
								
								
									
										218
									
								
								src/toolkit/shell-theme-context.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								src/toolkit/shell-theme-context.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,218 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include "shell-theme.h" | ||||
| #include "shell-theme-context.h" | ||||
|  | ||||
| struct _ShellThemeContext { | ||||
|   GObject parent; | ||||
|  | ||||
|   double resolution; | ||||
|   PangoFontDescription *font; | ||||
|   ShellThemeNode *root_node; | ||||
|   ShellTheme *theme; | ||||
| }; | ||||
|  | ||||
| struct _ShellThemeContextClass { | ||||
|   GObjectClass parent_class; | ||||
| }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   CHANGED, | ||||
|  | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL] = { 0, }; | ||||
|  | ||||
| G_DEFINE_TYPE (ShellThemeContext, shell_theme_context, G_TYPE_OBJECT) | ||||
|  | ||||
| static void | ||||
| shell_theme_context_finalize (GObject *object) | ||||
| { | ||||
|   ShellThemeContext *context = SHELL_THEME_CONTEXT (object); | ||||
|  | ||||
|   if (context->root_node) | ||||
|     g_object_unref (context->root_node); | ||||
|   if (context->theme) | ||||
|     g_object_unref (context->theme); | ||||
|    | ||||
|   pango_font_description_free (context->font); | ||||
|  | ||||
|   G_OBJECT_CLASS (shell_theme_context_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_theme_context_class_init (ShellThemeContextClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = shell_theme_context_finalize; | ||||
|  | ||||
|   signals[CHANGED] = | ||||
|     g_signal_new ("changed", | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   0, /* no default handler slot */ | ||||
|                   NULL, NULL, | ||||
|                   g_cclosure_marshal_VOID__VOID, | ||||
|                   G_TYPE_NONE, 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_theme_context_init (ShellThemeContext *context) | ||||
| { | ||||
|   context->resolution = 96.; | ||||
|   context->font = pango_font_description_from_string ("sans-serif 10"); | ||||
| } | ||||
|  | ||||
| ShellThemeContext * | ||||
| shell_theme_context_new (void) | ||||
| { | ||||
|   ShellThemeContext *context; | ||||
|  | ||||
|   context = g_object_new (SHELL_TYPE_THEME_CONTEXT, NULL); | ||||
|  | ||||
|   return context; | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_stage_destroy (ClutterStage *stage) | ||||
| { | ||||
|   ShellThemeContext *context = shell_theme_context_get_for_stage (stage); | ||||
|  | ||||
|   g_object_set_data (G_OBJECT (stage), "shell-theme-context", NULL); | ||||
|   g_object_unref (context); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * shell_theme_context_get_for_stage: | ||||
|  * @stage: a #ClutterStage | ||||
|  * | ||||
|  * Gets a singleton theme context associated with the stage. | ||||
|  * | ||||
|  * Return value: (transfer none): the singleton theme context for the stage | ||||
|  */ | ||||
| ShellThemeContext * | ||||
| shell_theme_context_get_for_stage (ClutterStage *stage) | ||||
| { | ||||
|   ShellThemeContext *context; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); | ||||
|  | ||||
|   context = g_object_get_data (G_OBJECT (stage), "shell-theme-context"); | ||||
|   if (context) | ||||
|     return context; | ||||
|  | ||||
|   context = shell_theme_context_new (); | ||||
|   g_object_set_data (G_OBJECT (stage), "shell-theme-context", context); | ||||
|   g_signal_connect (stage, "destroy", | ||||
|                     G_CALLBACK (on_stage_destroy), NULL); | ||||
|  | ||||
|   return context; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * shell_theme_context_set_theme: | ||||
|  * @context: a #ShellThemeContext | ||||
|  * | ||||
|  * Sets the default set of theme stylesheets for the context. This theme will | ||||
|  * be used for the root node and for nodes descending from it, unless some other | ||||
|  * style is explicitely specified. | ||||
|  */ | ||||
| void | ||||
| shell_theme_context_set_theme (ShellThemeContext          *context, | ||||
|                                ShellTheme                 *theme) | ||||
| { | ||||
|   g_return_if_fail (SHELL_IS_THEME_CONTEXT (context)); | ||||
|   g_return_if_fail (theme == NULL || SHELL_IS_THEME (theme)); | ||||
|  | ||||
|   if (context->theme != theme) | ||||
|     { | ||||
|       if (context->theme) | ||||
|         g_object_unref (context->theme); | ||||
|  | ||||
|       context->theme = theme; | ||||
|  | ||||
|       if (context->theme) | ||||
|         g_object_ref (context->theme); | ||||
|  | ||||
|       g_signal_emit (context, signals[CHANGED], 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * shell_theme_context_get_theme: | ||||
|  * @context: a #ShellThemeContext | ||||
|  * | ||||
|  * Gets the default theme for the context. See shell_theme_context_set_theme() | ||||
|  * | ||||
|  * Return value: (transfer none): the default theme for the context | ||||
|  */ | ||||
| ShellTheme * | ||||
| shell_theme_context_get_theme (ShellThemeContext *context) | ||||
| { | ||||
|   g_return_val_if_fail (SHELL_IS_THEME_CONTEXT (context), NULL); | ||||
|  | ||||
|   return context->theme; | ||||
| } | ||||
|  | ||||
| void | ||||
| shell_theme_context_set_resolution (ShellThemeContext *context, | ||||
|                                     double             resolution) | ||||
| { | ||||
|   g_return_if_fail (SHELL_IS_THEME_CONTEXT (context)); | ||||
|  | ||||
|   context->resolution = resolution; | ||||
| } | ||||
|  | ||||
| double | ||||
| shell_theme_context_get_resolution (ShellThemeContext *context) | ||||
| { | ||||
|   g_return_val_if_fail (SHELL_IS_THEME_CONTEXT (context), 96.); | ||||
|  | ||||
|   return context->resolution; | ||||
| } | ||||
|  | ||||
| void | ||||
| shell_theme_context_set_font (ShellThemeContext          *context, | ||||
|                               const PangoFontDescription *font) | ||||
| { | ||||
|   g_return_if_fail (SHELL_IS_THEME_CONTEXT (context)); | ||||
|  | ||||
|   if (context->font == font) | ||||
|     return; | ||||
|  | ||||
|   pango_font_description_free (context->font); | ||||
|   context->font = pango_font_description_copy (font); | ||||
| } | ||||
|  | ||||
| const PangoFontDescription * | ||||
| shell_theme_context_get_font (ShellThemeContext *context) | ||||
| { | ||||
|   g_return_val_if_fail (SHELL_IS_THEME_CONTEXT (context), NULL); | ||||
|  | ||||
|   return context->font; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * shell_theme_context_get_root_node: | ||||
|  * @context: a #ShellThemeContext | ||||
|  * | ||||
|  * Gets the root node of the tree of theme style nodes that associated with this | ||||
|  * context. For the node tree associated with a stage, this node represents | ||||
|  * styles applied to the stage itself. | ||||
|  * | ||||
|  * Return value: (transfer none): the root node of the context's style tree | ||||
|  */ | ||||
| ShellThemeNode * | ||||
| shell_theme_context_get_root_node (ShellThemeContext *context) | ||||
| { | ||||
|   if (context->root_node == NULL) | ||||
|     context->root_node = shell_theme_node_new (context, NULL, context->theme, | ||||
|                                                G_TYPE_NONE, NULL, NULL, NULL, NULL); | ||||
|  | ||||
|   return context->root_node; | ||||
| } | ||||
							
								
								
									
										40
									
								
								src/toolkit/shell-theme-context.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/toolkit/shell-theme-context.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| #ifndef __SHELL_THEME_CONTEXT_H__ | ||||
| #define __SHELL_THEME_CONTEXT_H__ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <pango/pango.h> | ||||
| #include "shell-theme-node.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| typedef struct _ShellThemeContextClass ShellThemeContextClass; | ||||
|  | ||||
| #define SHELL_TYPE_THEME_CONTEXT             (shell_theme_context_get_type ()) | ||||
| #define SHELL_THEME_CONTEXT(object)          (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_THEME_CONTEXT, ShellThemeContext)) | ||||
| #define SHELL_THEME_CONTEXT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_THEME_CONTEXT, ShellThemeContextClass)) | ||||
| #define SHELL_IS_THEME_CONTEXT(object)       (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_THEME_CONTEXT)) | ||||
| #define SHELL_IS_THEME_CONTEXT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_THEME_CONTEXT)) | ||||
| #define SHELL_THEME_CONTEXT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_THEME_CONTEXT, ShellThemeContextClass)) | ||||
|  | ||||
| GType shell_theme_context_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| ShellThemeContext *shell_theme_context_new           (void); | ||||
| ShellThemeContext *shell_theme_context_get_for_stage (ClutterStage *stage); | ||||
|  | ||||
| void                        shell_theme_context_set_theme      (ShellThemeContext          *context, | ||||
|                                                                 ShellTheme                 *theme); | ||||
| ShellTheme *                shell_theme_context_get_theme      (ShellThemeContext          *context); | ||||
|  | ||||
| void                        shell_theme_context_set_resolution (ShellThemeContext          *context, | ||||
|                                                                 gdouble                     resolution); | ||||
| double                      shell_theme_context_get_resolution (ShellThemeContext          *context); | ||||
| void                        shell_theme_context_set_font       (ShellThemeContext          *context, | ||||
|                                                                 const PangoFontDescription *font); | ||||
| const PangoFontDescription *shell_theme_context_get_font       (ShellThemeContext          *context); | ||||
|  | ||||
| ShellThemeNode *            shell_theme_context_get_root_node  (ShellThemeContext          *context); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __SHELL_THEME_CONTEXT_H__ */ | ||||
							
								
								
									
										2113
									
								
								src/toolkit/shell-theme-node.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2113
									
								
								src/toolkit/shell-theme-node.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										143
									
								
								src/toolkit/shell-theme-node.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								src/toolkit/shell-theme-node.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| #ifndef __SHELL_THEME_NODE_H__ | ||||
| #define __SHELL_THEME_NODE_H__ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include "shell-border-image.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| typedef struct _ShellTheme          ShellTheme; | ||||
| typedef struct _ShellThemeContext   ShellThemeContext; | ||||
|  | ||||
| typedef struct _ShellThemeNode      ShellThemeNode; | ||||
| typedef struct _ShellThemeNodeClass ShellThemeNodeClass; | ||||
|  | ||||
| #define SHELL_TYPE_THEME_NODE              (shell_theme_node_get_type ()) | ||||
| #define SHELL_THEME_NODE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_THEME_NODE, ShellThemeNode)) | ||||
| #define SHELL_THEME_NODE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass),     SHELL_TYPE_THEME_NODE, ShellThemeNodeClass)) | ||||
| #define SHELL_IS_THEME_NODE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_THEME_NODE)) | ||||
| #define SHELL_IS_THEME_NODE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass),     SHELL_TYPE_THEME_NODE)) | ||||
| #define SHELL_THEME_NODE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj),     SHELL_TYPE_THEME_NODE, ShellThemeNodeClass)) | ||||
|  | ||||
| typedef enum { | ||||
|     SHELL_SIDE_TOP, | ||||
|     SHELL_SIDE_RIGHT, | ||||
|     SHELL_SIDE_BOTTOM, | ||||
|     SHELL_SIDE_LEFT | ||||
| } ShellSide; | ||||
|  | ||||
| typedef enum { | ||||
|     SHELL_CORNER_TOPLEFT, | ||||
|     SHELL_CORNER_TOPRIGHT, | ||||
|     SHELL_CORNER_BOTTOMRIGHT, | ||||
|     SHELL_CORNER_BOTTOMLEFT | ||||
| } ShellCorner; | ||||
|  | ||||
| /* These are the CSS values; that doesn't mean we have to implement blink... */ | ||||
| typedef enum { | ||||
|     SHELL_TEXT_DECORATION_UNDERLINE    = 1 << 0, | ||||
|     SHELL_TEXT_DECORATION_OVERLINE     = 1 << 1, | ||||
|     SHELL_TEXT_DECORATION_LINE_THROUGH = 1 << 2, | ||||
|     SHELL_TEXT_DECORATION_BLINK        = 1 << 3 | ||||
| } ShellTextDecoration; | ||||
|  | ||||
| GType shell_theme_node_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| /* An element_type of G_TYPE_NONE means this style was created for the stage | ||||
|  * actor and matches a selector element name of 'stage' | ||||
|  */ | ||||
| ShellThemeNode *shell_theme_node_new (ShellThemeContext *context, | ||||
|                                       ShellThemeNode    *parent_node,   /* can be null */ | ||||
|                                       ShellTheme        *theme,         /* can be null */ | ||||
|                                       GType              element_type, | ||||
|                                       const char        *element_id, | ||||
|                                       const char        *element_class, | ||||
|                                       const char        *pseudo_class, | ||||
|                                       const char        *inline_style); | ||||
|  | ||||
| ShellThemeNode *shell_theme_node_get_parent (ShellThemeNode *node); | ||||
|  | ||||
| ShellTheme *shell_theme_node_get_theme (ShellThemeNode *node); | ||||
|  | ||||
| GType       shell_theme_node_get_element_type  (ShellThemeNode *node); | ||||
| const char *shell_theme_node_get_element_id    (ShellThemeNode *node); | ||||
| const char *shell_theme_node_get_element_class (ShellThemeNode *node); | ||||
| const char *shell_theme_node_get_pseudo_class  (ShellThemeNode *node); | ||||
|  | ||||
| /* Generic getters ... these are not cached so are less efficient. The other | ||||
|  * reason for adding the more specific version is that we can handle the | ||||
|  * details of the actual CSS rules, which can be complicated, especially | ||||
|  * for fonts | ||||
|  */ | ||||
| gboolean shell_theme_node_get_color (ShellThemeNode *node, | ||||
|                                      const char     *property_name, | ||||
|                                      gboolean        inherit, | ||||
|                                      ClutterColor   *color); | ||||
|  | ||||
| gboolean shell_theme_node_get_double (ShellThemeNode *node, | ||||
|                                       const char     *property_name, | ||||
|                                       gboolean        inherit, | ||||
|                                       double         *value); | ||||
|  | ||||
| /* The length here is already resolved to pixels | ||||
|  */ | ||||
| gboolean shell_theme_node_get_length (ShellThemeNode *node, | ||||
|                                       const char     *property_name, | ||||
|                                       gboolean        inherit, | ||||
|                                       gdouble        *length); | ||||
|  | ||||
| /* Specific getters for particular properties: cached | ||||
|  */ | ||||
| void shell_theme_node_get_background_color (ShellThemeNode *node, | ||||
|                                             ClutterColor   *color); | ||||
| void shell_theme_node_get_foreground_color (ShellThemeNode *node, | ||||
|                                             ClutterColor   *color); | ||||
|  | ||||
| const char *shell_theme_node_get_background_image (ShellThemeNode *node); | ||||
|  | ||||
| double shell_theme_node_get_border_width  (ShellThemeNode *node, | ||||
|                                            ShellSide       side); | ||||
| double shell_theme_node_get_border_radius (ShellThemeNode *node, | ||||
|                                            ShellCorner     corner); | ||||
| void   shell_theme_node_get_border_color  (ShellThemeNode *node, | ||||
|                                            ShellSide       side, | ||||
|                                            ClutterColor   *color); | ||||
|  | ||||
| double  shell_theme_node_get_padding      (ShellThemeNode *node, | ||||
|                                            ShellSide       side); | ||||
|  | ||||
| ShellTextDecoration shell_theme_node_get_text_decoration (ShellThemeNode *node); | ||||
|  | ||||
| /* Font rule processing is pretty complicated, so we just hardcode it | ||||
|  * under the standard font/font-family/font-size/etc names. This means | ||||
|  * you can't have multiple separate styled fonts for a single item, | ||||
|  * but that should be OK. | ||||
|  */ | ||||
| const PangoFontDescription *shell_theme_node_get_font (ShellThemeNode *node); | ||||
|  | ||||
| ShellBorderImage *shell_theme_node_get_border_image (ShellThemeNode *node); | ||||
|  | ||||
| /* Helpers for get_preferred_width()/get_preferred_height() ClutterActor vfuncs */ | ||||
| void shell_theme_node_adjust_for_height       (ShellThemeNode  *node, | ||||
|                                                float           *for_height); | ||||
| void shell_theme_node_adjust_preferred_width  (ShellThemeNode  *node, | ||||
|                                                float           *min_width_p, | ||||
|                                                float           *natural_width_p); | ||||
| void shell_theme_node_adjust_for_width        (ShellThemeNode  *node, | ||||
|                                                float           *for_width); | ||||
| void shell_theme_node_adjust_preferred_height (ShellThemeNode  *node, | ||||
|                                                float           *min_height_p, | ||||
|                                                float           *natural_height_p); | ||||
|  | ||||
| /* Helper for allocate() ClutterActor vfunc */ | ||||
| void shell_theme_node_get_content_box         (ShellThemeNode        *node, | ||||
|                                                const ClutterActorBox *actor_box, | ||||
|                                                ClutterActorBox       *content_box); | ||||
|  | ||||
| gboolean shell_theme_node_geometry_equal (ShellThemeNode *node, | ||||
|                                           ShellThemeNode *other); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __SHELL_THEME_NODE_H__ */ | ||||
							
								
								
									
										20
									
								
								src/toolkit/shell-theme-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/toolkit/shell-theme-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| #ifndef __SHELL_THEME_PRIVATE_H__ | ||||
| #define __SHELL_THEME_PRIVATE_H__ | ||||
|  | ||||
| #include <libcroco/libcroco.h> | ||||
| #include "shell-theme.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| GPtrArray *_shell_theme_get_matched_properties (ShellTheme       *theme, | ||||
|                                                 ShellThemeNode   *node); | ||||
|  | ||||
| /* Resolve an URL from the stylesheet to a filename */ | ||||
| char *_shell_theme_resolve_url (ShellTheme   *theme, | ||||
|                                 CRStyleSheet *base_stylesheet, | ||||
|                                 const char   *url); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __SHELL_THEME_PRIVATE_H__ */ | ||||
							
								
								
									
										1029
									
								
								src/toolkit/shell-theme.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1029
									
								
								src/toolkit/shell-theme.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										28
									
								
								src/toolkit/shell-theme.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/toolkit/shell-theme.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| #ifndef __SHELL_THEME_H__ | ||||
| #define __SHELL_THEME_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include "shell-theme-node.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| typedef struct _ShellThemeClass ShellThemeClass; | ||||
|  | ||||
| #define SHELL_TYPE_THEME              (shell_theme_get_type ()) | ||||
| #define SHELL_THEME(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_THEME, ShellTheme)) | ||||
| #define SHELL_THEME_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_THEME, ShellThemeClass)) | ||||
| #define SHELL_IS_THEME(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_THEME)) | ||||
| #define SHELL_IS_THEME_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_THEME)) | ||||
| #define SHELL_THEME_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_THEME, ShellThemeClass)) | ||||
|  | ||||
| GType  shell_theme_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| ShellTheme *shell_theme_new (const char *application_stylesheet, | ||||
|                              const char *theme_stylesheet, | ||||
|                              const char *default_stylesheet); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __SHELL_THEME_H__ */ | ||||
							
								
								
									
										392
									
								
								src/toolkit/test-theme.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										392
									
								
								src/toolkit/test-theme.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,392 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include "shell-theme.h" | ||||
| #include "shell-theme-context.h" | ||||
| #include <math.h> | ||||
| #include <string.h> | ||||
|  | ||||
| static ShellThemeNode *root; | ||||
| static ShellThemeNode *group1; | ||||
| static ShellThemeNode *text1; | ||||
| static ShellThemeNode *text2; | ||||
| static ShellThemeNode *group2; | ||||
| static ShellThemeNode *text3; | ||||
| static ShellThemeNode *text4; | ||||
| static ShellThemeNode *group3; | ||||
| static ShellThemeNode *cairo_texture; | ||||
| static gboolean fail; | ||||
|  | ||||
| static const char *test; | ||||
|  | ||||
| static void | ||||
| assert_font (ShellThemeNode *node, | ||||
| 	     const char     *node_description, | ||||
| 	     const char     *expected) | ||||
| { | ||||
|   char *value = pango_font_description_to_string (shell_theme_node_get_font (node)); | ||||
|  | ||||
|   if (strcmp (expected, value) != 0) | ||||
|     { | ||||
|       g_print ("%s: %s.font: expected: %s, got: %s\n", | ||||
| 	       test, node_description, expected, value); | ||||
|       fail = TRUE; | ||||
|     } | ||||
|  | ||||
|   g_free (value); | ||||
| } | ||||
|  | ||||
| static char * | ||||
| text_decoration_to_string (ShellTextDecoration decoration) | ||||
| { | ||||
|   GString *result = g_string_new (NULL); | ||||
|  | ||||
|   if (decoration & SHELL_TEXT_DECORATION_UNDERLINE) | ||||
|     g_string_append(result, " underline"); | ||||
|   if (decoration & SHELL_TEXT_DECORATION_OVERLINE) | ||||
|     g_string_append(result, " overline"); | ||||
|   if (decoration & SHELL_TEXT_DECORATION_LINE_THROUGH) | ||||
|     g_string_append(result, " line_through"); | ||||
|   if (decoration & SHELL_TEXT_DECORATION_BLINK) | ||||
|     g_string_append(result, " blink"); | ||||
|  | ||||
|   if (result->len > 0) | ||||
|     g_string_erase (result, 0, 1); | ||||
|   else | ||||
|     g_string_append(result, "none"); | ||||
|  | ||||
|   return g_string_free (result, FALSE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| assert_text_decoration (ShellThemeNode     *node, | ||||
| 			const char         *node_description, | ||||
| 			ShellTextDecoration expected) | ||||
| { | ||||
|   ShellTextDecoration value = shell_theme_node_get_text_decoration (node); | ||||
|   if (expected != value) | ||||
|     { | ||||
|       char *es = text_decoration_to_string (expected); | ||||
|       char *vs = text_decoration_to_string (value); | ||||
|  | ||||
|       g_print ("%s: %s.text-decoration: expected: %s, got: %s\n", | ||||
| 	       test, node_description, es, vs); | ||||
|       fail = TRUE; | ||||
|  | ||||
|       g_free (es); | ||||
|       g_free (vs); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| assert_foreground_color (ShellThemeNode *node, | ||||
| 			 const char     *node_description, | ||||
| 			 guint32         expected) | ||||
| { | ||||
|   ClutterColor color; | ||||
|   shell_theme_node_get_foreground_color (node, &color); | ||||
|   guint32 value = clutter_color_to_pixel (&color); | ||||
|  | ||||
|   if (expected != value) | ||||
|     { | ||||
|       g_print ("%s: %s.color: expected: #%08x, got: #%08x\n", | ||||
| 	       test, node_description, expected, value); | ||||
|       fail = TRUE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| assert_background_color (ShellThemeNode *node, | ||||
| 			 const char     *node_description, | ||||
| 			 guint32         expected) | ||||
| { | ||||
|   ClutterColor color; | ||||
|   shell_theme_node_get_background_color (node, &color); | ||||
|   guint32 value = clutter_color_to_pixel (&color); | ||||
|  | ||||
|   if (expected != value) | ||||
|     { | ||||
|       g_print ("%s: %s.background-color: expected: #%08x, got: #%08x\n", | ||||
| 	       test, node_description, expected, value); | ||||
|       fail = TRUE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static const char * | ||||
| side_to_string (ShellSide side) | ||||
| { | ||||
|   switch (side) | ||||
|     { | ||||
|     case SHELL_SIDE_TOP: | ||||
|       return "top"; | ||||
|     case SHELL_SIDE_RIGHT: | ||||
|       return "right"; | ||||
|     case SHELL_SIDE_BOTTOM: | ||||
|       return "bottom"; | ||||
|     case SHELL_SIDE_LEFT: | ||||
|       return "left"; | ||||
|     } | ||||
|  | ||||
|   return "<unknown>"; | ||||
| } | ||||
|  | ||||
| static void | ||||
| assert_border_color (ShellThemeNode *node, | ||||
|                      const char     *node_description, | ||||
|                      ShellSide       side, | ||||
|                      guint32         expected) | ||||
| { | ||||
|   ClutterColor color; | ||||
|   shell_theme_node_get_border_color (node, side, &color); | ||||
|   guint32 value = clutter_color_to_pixel (&color); | ||||
|  | ||||
|   if (expected != value) | ||||
|     { | ||||
|       g_print ("%s: %s.border-%s-color: expected: #%08x, got: #%08x\n", | ||||
| 	       test, node_description, side_to_string (side), expected, value); | ||||
|       fail = TRUE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| assert_background_image (ShellThemeNode *node, | ||||
| 			 const char     *node_description, | ||||
| 			 const char     *expected) | ||||
| { | ||||
|   const char *value = shell_theme_node_get_background_image (node); | ||||
|   if (expected == NULL) | ||||
|     expected = "(null)"; | ||||
|   if (value == NULL) | ||||
|     value = "(null)"; | ||||
|  | ||||
|   if (strcmp (expected, value) != 0) | ||||
|     { | ||||
|       g_print ("%s: %s.background-image: expected: %s, got: %s\n", | ||||
| 	       test, node_description, expected, value); | ||||
|       fail = TRUE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| #define LENGTH_EPSILON 0.001 | ||||
|  | ||||
| static void | ||||
| assert_length (const char     *node_description, | ||||
| 	       const char     *property_description, | ||||
| 	       double          expected, | ||||
| 	       double          value) | ||||
| { | ||||
|   if (fabs (expected - value) > LENGTH_EPSILON) | ||||
|     { | ||||
|       g_print ("%s %s.%s: expected: %3f, got: %3f\n", | ||||
| 	       test, node_description, property_description, expected, value); | ||||
|       fail = TRUE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_defaults (void) | ||||
| { | ||||
|   test = "defaults"; | ||||
|   /* font comes from context */ | ||||
|   assert_font (root, "stage", "sans-serif 12"); | ||||
|   /* black is the default foreground color */ | ||||
|   assert_foreground_color (root, "stage", 0x00000ff); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_lengths (void) | ||||
| { | ||||
|   test = "lengths"; | ||||
|   /* 12pt == 16px at 96dpi */ | ||||
|   assert_length ("group1", "padding-top", 16., | ||||
| 		 shell_theme_node_get_padding (group1, SHELL_SIDE_TOP)); | ||||
|   /* 12px == 12px */ | ||||
|   assert_length ("group1", "padding-right", 12., | ||||
| 		 shell_theme_node_get_padding (group1, SHELL_SIDE_RIGHT)); | ||||
|   /* 2em == 32px (with a 12pt font) */ | ||||
|   assert_length ("group1", "padding-bottom", 32., | ||||
| 		 shell_theme_node_get_padding (group1, SHELL_SIDE_BOTTOM)); | ||||
|   /* 1in == 72pt == 96px, at 96dpi */ | ||||
|   assert_length ("group1", "padding-left", 96., | ||||
| 		 shell_theme_node_get_padding (group1, SHELL_SIDE_LEFT)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_classes (void) | ||||
| { | ||||
|   test = "classes"; | ||||
|   /* .special-text class overrides size and style; | ||||
|    * the ClutterTexture.special-text selector doesn't match */ | ||||
|   assert_font (text1, "text1", "sans-serif Italic 32px"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_type_inheritance (void) | ||||
| { | ||||
|   test = "type_inheritance"; | ||||
|   /* From ClutterTexture element selector */ | ||||
|   assert_length ("cairoTexture", "padding-top", 10., | ||||
| 		 shell_theme_node_get_padding (cairo_texture, SHELL_SIDE_TOP)); | ||||
|   /* From ClutterCairoTexture element selector */ | ||||
|   assert_length ("cairoTexture", "padding-right", 20., | ||||
| 		 shell_theme_node_get_padding (cairo_texture, SHELL_SIDE_RIGHT)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_adjacent_selector (void) | ||||
| { | ||||
|   test = "adjacent_selector"; | ||||
|   /* #group1 > #text1 matches text1 */ | ||||
|   assert_foreground_color (text1, "text1", 0x00ff00ff); | ||||
|   /* stage > #text2 doesn't match text2 */ | ||||
|   assert_foreground_color (text2, "text2", 0x000000ff); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_padding (void) | ||||
| { | ||||
|   test = "padding"; | ||||
|   /* Test that a 4-sided padding property assigns the right paddings to | ||||
|    * all sides */ | ||||
|   assert_length ("group2", "padding-top", 1., | ||||
| 		 shell_theme_node_get_padding (group2, SHELL_SIDE_TOP)); | ||||
|   assert_length ("group2", "padding-right", 2., | ||||
| 		 shell_theme_node_get_padding (group2, SHELL_SIDE_RIGHT)); | ||||
|   assert_length ("group2", "padding-bottom", 3., | ||||
| 		 shell_theme_node_get_padding (group2, SHELL_SIDE_BOTTOM)); | ||||
|   assert_length ("group2", "padding-left", 4., | ||||
| 		 shell_theme_node_get_padding (group2, SHELL_SIDE_LEFT)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_border (void) | ||||
| { | ||||
|   test = "border"; | ||||
|  | ||||
|   /* group2 is defined as having a thin black border along the top three | ||||
|    * sides with rounded joins, then a square-joined green border at the | ||||
|    * botttom | ||||
|    */ | ||||
|  | ||||
|   assert_length ("group2", "border-top-width", 2., | ||||
| 		 shell_theme_node_get_border_width (group2, SHELL_SIDE_TOP)); | ||||
|   assert_length ("group2", "border-right-width", 2., | ||||
| 		 shell_theme_node_get_border_width (group2, SHELL_SIDE_RIGHT)); | ||||
|   assert_length ("group2", "border-bottom-width", 5., | ||||
| 		 shell_theme_node_get_border_width (group2, SHELL_SIDE_BOTTOM)); | ||||
|   assert_length ("group2", "border-left-width", 2., | ||||
| 		 shell_theme_node_get_border_width (group2, SHELL_SIDE_LEFT)); | ||||
|  | ||||
|   assert_border_color (group2, "group2", SHELL_SIDE_TOP,    0x000000ff); | ||||
|   assert_border_color (group2, "group2", SHELL_SIDE_RIGHT,  0x000000ff); | ||||
|   assert_border_color (group2, "group2", SHELL_SIDE_BOTTOM, 0x0000ffff); | ||||
|   assert_border_color (group2, "group2", SHELL_SIDE_LEFT,   0x000000ff); | ||||
|  | ||||
|   assert_length ("group2", "border-radius-topleft", 10., | ||||
| 		 shell_theme_node_get_border_radius (group2, SHELL_CORNER_TOPLEFT)); | ||||
|   assert_length ("group2", "border-radius-topright", 10., | ||||
| 		 shell_theme_node_get_border_radius (group2, SHELL_CORNER_TOPRIGHT)); | ||||
|   assert_length ("group2", "border-radius-bottomright", 0., | ||||
| 		 shell_theme_node_get_border_radius (group2, SHELL_CORNER_BOTTOMRIGHT)); | ||||
|   assert_length ("group2", "border-radius-bottomleft", 0., | ||||
| 		 shell_theme_node_get_border_radius (group2, SHELL_CORNER_BOTTOMLEFT)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_background (void) | ||||
| { | ||||
|   test = "background"; | ||||
|   /* group1 has a background: shortcut property setting color and image */ | ||||
|   assert_background_color (group1, "group1", 0xff0000ff); | ||||
|   assert_background_image (group1, "group1", "toolkit/some-background.png"); | ||||
|   /* text1 inherits the background image but not the color */ | ||||
|   assert_background_color (text1,  "text1",  0x00000000); | ||||
|   assert_background_image (text1,  "text1",  "toolkit/some-background.png"); | ||||
|   /* text1 inherits inherits both, but then background: none overrides both */ | ||||
|   assert_background_color (text2,  "text2",  0x00000000); | ||||
|   assert_background_image (text2,  "text2",  NULL); | ||||
|   /* background-image property */ | ||||
|   assert_background_image (group2, "group2", "toolkit/other-background.png"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_font (void) | ||||
| { | ||||
|   test = "font"; | ||||
|   /* font specified with font: */ | ||||
|   assert_font (group2, "group2", "serif Italic 12px"); | ||||
|   /* text3 inherits and overrides individually properties */ | ||||
|   assert_font (text3,  "text3",  "serif Bold Oblique Small-Caps 24px"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_pseudo_class (void) | ||||
| { | ||||
|   test = "pseudo_class"; | ||||
|   /* text4 has :visited and :hover pseudo-classes, so should pick up both of these */ | ||||
|   assert_foreground_color (text4,   "text4",  0x888888ff); | ||||
|   assert_text_decoration  (text4,   "text4",  SHELL_TEXT_DECORATION_UNDERLINE); | ||||
|   /* :hover pseudo-class matches, but class doesn't match */ | ||||
|   assert_text_decoration  (group3,  "group3", 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_inline_style (void) | ||||
| { | ||||
|   test = "inline_style"; | ||||
|   /* These properties come from the inline-style specified when creating the node */ | ||||
|   assert_foreground_color (text3,   "text3",  0x00000ffff); | ||||
|   assert_length ("text3", "padding-bottom", 12., | ||||
| 		 shell_theme_node_get_padding (text3, SHELL_SIDE_BOTTOM)); | ||||
| } | ||||
|  | ||||
| int | ||||
| main (int argc, char **argv) | ||||
| { | ||||
|   ShellTheme *theme; | ||||
|   ShellThemeContext *context; | ||||
|  | ||||
|   clutter_init (&argc, &argv); | ||||
|  | ||||
|   theme = shell_theme_new ("toolkit/test-theme.css", | ||||
| 			   NULL, NULL); | ||||
|  | ||||
|   context = shell_theme_context_new (); | ||||
|   shell_theme_context_set_theme (context, theme); | ||||
|   shell_theme_context_set_resolution (context, 96.); | ||||
|   shell_theme_context_set_font (context, | ||||
| 				pango_font_description_from_string ("sans-serif 12")); | ||||
|  | ||||
|   root = shell_theme_context_get_root_node (context); | ||||
|   group1 = shell_theme_node_new (context, root, NULL, | ||||
| 				 CLUTTER_TYPE_GROUP, "group1", NULL, NULL, NULL); | ||||
|   text1 = shell_theme_node_new  (context, group1, NULL, | ||||
| 				 CLUTTER_TYPE_TEXT, "text1", "special-text", NULL, NULL); | ||||
|   text2 = shell_theme_node_new  (context, group1, NULL, | ||||
| 				 CLUTTER_TYPE_TEXT, "text2", NULL, NULL, NULL); | ||||
|   group2 = shell_theme_node_new (context, root, NULL, | ||||
| 				 CLUTTER_TYPE_GROUP, "group2", NULL, NULL, NULL); | ||||
|   text3 = shell_theme_node_new  (context, group2, NULL, | ||||
| 				 CLUTTER_TYPE_TEXT, "text3", NULL, NULL, | ||||
|                                  "color: #0000ff; padding-bottom: 12px;"); | ||||
|   text4 = shell_theme_node_new  (context, group2, NULL, | ||||
| 				 CLUTTER_TYPE_TEXT, "text4", NULL, "visited hover", NULL); | ||||
|   group3 = shell_theme_node_new (context, group2, NULL, | ||||
| 				 CLUTTER_TYPE_GROUP, "group3", NULL, "hover", NULL); | ||||
|   cairo_texture = shell_theme_node_new (context, root, NULL, | ||||
| 					CLUTTER_TYPE_CAIRO_TEXTURE, "cairoTexture", NULL, NULL, NULL); | ||||
|  | ||||
|   test_defaults (); | ||||
|   test_lengths (); | ||||
|   test_classes (); | ||||
|   test_type_inheritance (); | ||||
|   test_adjacent_selector (); | ||||
|   test_padding (); | ||||
|   test_border (); | ||||
|   test_background (); | ||||
|   test_font (); | ||||
|   test_pseudo_class (); | ||||
|   test_inline_style (); | ||||
|  | ||||
|   return fail ? 1 : 0; | ||||
| } | ||||
							
								
								
									
										73
									
								
								src/toolkit/test-theme.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								src/toolkit/test-theme.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| stage { | ||||
| } | ||||
|  | ||||
| #group1 { | ||||
|     padding: 12pt; | ||||
|     padding-right: 12px; | ||||
|     padding-bottom: 2em; | ||||
|     padding-left: 1in; | ||||
|  | ||||
|     background: #ff0000 url('some-background.png'); | ||||
| } | ||||
|  | ||||
| #text1 { | ||||
|     background-image: inherit; | ||||
| } | ||||
|  | ||||
| .special-text { | ||||
|     font-size: 24pt; | ||||
|     font-style: italic; | ||||
| } | ||||
|  | ||||
| ClutterTexture.special-text { | ||||
|     font-weight: bold; | ||||
| } | ||||
|  | ||||
| #text2 { | ||||
|     background: inherit; | ||||
|     background: none; /* also overrides the color */ | ||||
| } | ||||
|  | ||||
| #group2 { | ||||
|     font: italic 12px serif; | ||||
| } | ||||
|  | ||||
| #text3 { | ||||
|     font-variant: small-caps; | ||||
|     font-weight: bold; | ||||
|     font-style: oblique; | ||||
|     font-size: 200%; | ||||
| } | ||||
|  | ||||
| ClutterTexture { | ||||
|     padding: 10px; | ||||
| } | ||||
|  | ||||
| ClutterCairoTexture { | ||||
|     padding-right: 20px; | ||||
| } | ||||
|  | ||||
| #group1 > #text1 { | ||||
|     color: #00ff00; | ||||
| } | ||||
|  | ||||
| stage > #text2 { | ||||
|     color: #ff0000; | ||||
| } | ||||
|  | ||||
| #group2 { | ||||
|     background-image: url('other-background.png'); | ||||
|     padding: 1px 2px 3px 4px; | ||||
|  | ||||
|     border: 2px solid #000000; | ||||
|     border-bottom: 5px solid #0000ff; | ||||
|     border-radius: 10px 10px 0px 0px; | ||||
| } | ||||
|  | ||||
| ClutterText:hover { | ||||
|     text-decoration: underline; | ||||
| } | ||||
|  | ||||
| ClutterText:visited { | ||||
|     color: #888888; | ||||
| } | ||||
							
								
								
									
										21
									
								
								tests/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| noinst_SCRIPTS = run-test.sh | ||||
| EXTRA_DIST = run-test.sh.in | ||||
|  | ||||
| TEST_JS =					\ | ||||
| 	testcommon/ui.js			\ | ||||
| 	interactive/box-layout.js | ||||
| EXTRA_DIST += $(TEST_JS) | ||||
|  | ||||
| TEST_MISC =					\ | ||||
| 	testcommon/test.css | ||||
| EXTRA_DIST += $(TEST_MISC) | ||||
|  | ||||
| # We substitute in bindir so it works as an autostart | ||||
| # file when built in a non-system prefix | ||||
| run-test.sh: run-test.sh.in | ||||
| 	$(AM_V_GEN) sed \ | ||||
| 	    -e "s|@GJS_JS_DIR[@]|$(GJS_JS_DIR)|" \ | ||||
| 	    -e "s|@GJS_JS_NATIVE_DIR[@]|$(GJS_JS_NATIVE_DIR)|" \ | ||||
| 	    -e "s|@MUTTER_LIB_DIR[@]|$(MUTTER_LIB_DIR)|" \ | ||||
| 	    -e "s|@srcdir[@]|$(srcdir)|" \ | ||||
| 	    $< > $@ && chmod a+x $@ | ||||
							
								
								
									
										63
									
								
								tests/interactive/borders.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								tests/interactive/borders.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Nbtk = imports.gi.Nbtk; | ||||
|  | ||||
| const UI = imports.testcommon.ui; | ||||
|  | ||||
| UI.init(); | ||||
| let stage = Clutter.Stage.get_default(); | ||||
| stage.width = 600; | ||||
| stage.height = 700; | ||||
|  | ||||
| let vbox = new Nbtk.BoxLayout({ vertical: true, | ||||
| 				width: stage.width, | ||||
| 			        height: stage.height, | ||||
|                                 spacing: 20, | ||||
|                                 style: 'padding: 10px; background: #ffee88;' }); | ||||
| stage.add_actor(vbox); | ||||
|  | ||||
| vbox.add(new Nbtk.Label({ text: "Hello World", | ||||
|                           style: 'border: 1px solid black; ' | ||||
|                                  + 'padding: 5px;' })); | ||||
|  | ||||
| vbox.add(new Nbtk.Label({ text: "Hello Round World", | ||||
|                           style: 'border: 3px solid green; ' | ||||
|                                  + 'border-radius: 8px; ' | ||||
|                                  + 'padding: 5px;' })); | ||||
|  | ||||
| vbox.add(new Nbtk.Label({ text: "Hello Background", | ||||
|                           style: 'border: 3px solid green; ' | ||||
|                                  + 'border-radius: 8px; ' | ||||
|                                  + 'background: white; ' | ||||
|                                  + 'padding: 5px;' })); | ||||
|  | ||||
| vbox.add(new Nbtk.Label({ text: "Border, Padding, Content: 20px" })); | ||||
|  | ||||
| let b1 = new Nbtk.BoxLayout({ vertical: true, | ||||
|                               style: 'border: 20px solid black; ' | ||||
|                                      + 'background: white; ' | ||||
|                                      + 'padding: 20px;' }); | ||||
| vbox.add(b1); | ||||
|  | ||||
| b1.add(new Nbtk.BoxLayout({ width: 20, height: 20, | ||||
|                             style: 'background: black' })); | ||||
|  | ||||
| vbox.add(new Nbtk.Label({ text: "Translucent blue border, with rounding", | ||||
|                           style: 'border: 20px solid rgba(0, 0, 255, 0.2); ' | ||||
|                                  + 'border-radius: 10px; ' | ||||
|                                  + 'background: white; ' | ||||
|                                  + 'padding: 10px;' })); | ||||
|  | ||||
| vbox.add(new Nbtk.Label({ text: "Transparent border", | ||||
|                           style: 'border: 20px solid transparent; ' | ||||
|                                  + 'background: white; ' | ||||
|                                  + 'padding: 10px;' })); | ||||
|  | ||||
| vbox.add(new Nbtk.Label({ text: "Border Image", | ||||
|                           style_class: "border-image", | ||||
|                           style: "padding: 10px;" })); | ||||
|  | ||||
| stage.show(); | ||||
| Clutter.main(); | ||||
| stage.destroy(); | ||||
							
								
								
									
										87
									
								
								tests/interactive/box-layout.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								tests/interactive/box-layout.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Nbtk = imports.gi.Nbtk; | ||||
|  | ||||
| const UI = imports.testcommon.ui; | ||||
|  | ||||
| UI.init(); | ||||
| let stage = Clutter.Stage.get_default(); | ||||
|  | ||||
| let vbox = new Nbtk.BoxLayout({ vertical: true, | ||||
|                                 width: stage.width, | ||||
|                                 height: stage.height, | ||||
|                                 spacing: 10, | ||||
|                                 style: 'padding: 10px' }); | ||||
| stage.add_actor(vbox); | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| let colored_boxes = new Nbtk.BoxLayout({ vertical: true, | ||||
|                                          width:  200, | ||||
|                                          height: 200, | ||||
|                                          style: 'border: 2px solid black;' }); | ||||
| vbox.add(colored_boxes, { x_fill: false, | ||||
|                           x_align: Nbtk.Align.MIDDLE }); | ||||
|  | ||||
| let b2 = new Nbtk.BoxLayout({ style: 'border: 2px solid #666666' }); | ||||
| colored_boxes.add(b2, { expand: true }); | ||||
|  | ||||
| b2.add(new Nbtk.Label({ text: "Expand", | ||||
|                         style: 'border: 1px solid #aaaaaa; ' | ||||
|                                + 'background: #ffeecc' }), | ||||
|        { expand: true }); | ||||
| b2.add(new Nbtk.Label({ text: "Expand\nNo Fill", | ||||
|                         style: 'border: 1px solid #aaaaaa; ' | ||||
|                                + 'background: #ccffaa' }), | ||||
|        { expand: true, | ||||
|          x_fill: false, | ||||
|          x_align: Nbtk.Align.MIDDLE, | ||||
|          y_fill: false, | ||||
|          y_align: Nbtk.Align.MIDDLE }); | ||||
|  | ||||
| colored_boxes.add(new Nbtk.Label({ text: "Default", | ||||
|                                    style: 'border: 1px solid #aaaaaa; ' | ||||
|                                           + 'background: #cceeff' })); | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| function createCollapsableBox(width) { | ||||
|     let b = new Nbtk.BoxLayout({ width: width, | ||||
|                                  style: 'border: 1px solid black;' | ||||
|                                         + 'font: 13px Sans;' }); | ||||
|     b.add(new Nbtk.Label({ text: "Very Very Very Long", | ||||
|                            style: 'background: #ffaacc;' | ||||
|                                   + 'padding: 5px; ' | ||||
|                                   + 'border: 1px solid #666666;' }), | ||||
|           { expand: true }); | ||||
|     b.add(new Nbtk.Label({ text: "Very Very Long", | ||||
|                            style: 'background: #ffeecc; ' | ||||
|                                   + 'padding: 5px; ' | ||||
|                                   + 'border: 1px solid #666666;' }), | ||||
|           { expand: true }); | ||||
|     b.add(new Nbtk.Label({ text: "Very Long", | ||||
|                            style: 'background: #ccffaa; ' | ||||
|                                   + 'padding: 5px; ' | ||||
|                                   + 'border: 1px solid #666666;' }), | ||||
|           { expand: true }); | ||||
|     b.add(new Nbtk.Label({ text: "Short", | ||||
|                            style: 'background: #cceeff; ' | ||||
|                                   + 'padding: 5px; ' | ||||
|                                   + 'border: 1px solid #666666;' }), | ||||
|           { expand: true }); | ||||
|  | ||||
|     return b; | ||||
| } | ||||
|  | ||||
| for (let width = 200; width <= 500; width += 60 ) { | ||||
|     vbox.add(createCollapsableBox (width), | ||||
|              { x_fill: false, | ||||
|                x_align: Nbtk.Align.MIDDLE }); | ||||
| } | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
|  | ||||
| stage.show(); | ||||
| Clutter.main(); | ||||
							
								
								
									
										39
									
								
								tests/interactive/css-fonts.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								tests/interactive/css-fonts.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Nbtk = imports.gi.Nbtk; | ||||
|  | ||||
| const UI = imports.testcommon.ui; | ||||
|  | ||||
| UI.init(); | ||||
| let stage = Clutter.Stage.get_default(); | ||||
|  | ||||
| let b = new Nbtk.BoxLayout({ vertical: true, | ||||
| 			     width: stage.width, | ||||
| 			     height: stage.height }); | ||||
| stage.add_actor(b); | ||||
|  | ||||
| let t; | ||||
|  | ||||
| t = new Nbtk.Label({ "text": "Bold", style_class: "bold" }); | ||||
| b.add(t); | ||||
| t = new Nbtk.Label({ "text": "Monospace", style_class: "monospace" }); | ||||
| b.add(t); | ||||
| t = new Nbtk.Label({ "text": "Italic", style_class: "italic" }); | ||||
| b.add(t); | ||||
| t = new Nbtk.Label({ "text": "Bold Italic", style_class: "bold italic" }); | ||||
| b.add(t); | ||||
| t = new Nbtk.Label({ "text": "Big Italic", style_class: "big italic" }); | ||||
| b.add(t); | ||||
| t = new Nbtk.Label({ "text": "Big Bold", style_class: "big bold" }); | ||||
| b.add(t); | ||||
|  | ||||
| let b2 = new Nbtk.BoxLayout({ vertical: true, style_class: "monospace" }); | ||||
| b.add(b2); | ||||
| t = new Nbtk.Label({ "text": "Big Monospace", style_class: "big" }); | ||||
| b2.add(t); | ||||
| t = new Nbtk.Label({ "text": "Italic Monospace", style_class: "italic" }); | ||||
| b2.add(t); | ||||
|  | ||||
| stage.show(); | ||||
| Clutter.main(); | ||||
							
								
								
									
										47
									
								
								tests/interactive/inline-style.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								tests/interactive/inline-style.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Nbtk = imports.gi.Nbtk; | ||||
|  | ||||
| const UI = imports.testcommon.ui; | ||||
|  | ||||
| UI.init(); | ||||
| let stage = Clutter.Stage.get_default(); | ||||
|  | ||||
| let vbox = new Nbtk.BoxLayout({ vertical: true, | ||||
|   			        width: stage.width, | ||||
| 			        height: stage.height }); | ||||
| stage.add_actor(vbox); | ||||
|  | ||||
| let hbox = new Nbtk.BoxLayout({ spacing: 12 }); | ||||
| vbox.add(hbox); | ||||
|  | ||||
| let text = new Nbtk.Label({ text: "Styled Text" }); | ||||
| vbox.add (text); | ||||
|  | ||||
| let size = 24; | ||||
| function update_size() { | ||||
|     text.style = 'font-size: ' + size + 'pt'; | ||||
| } | ||||
| update_size(); | ||||
|  | ||||
| let button; | ||||
|  | ||||
| button = new Nbtk.Button ({ label: 'Smaller' }); | ||||
| hbox.add (button); | ||||
| button.connect('clicked', function() { | ||||
|                    size /= 1.2; | ||||
|                    update_size (); | ||||
|                }); | ||||
|  | ||||
| button = new Nbtk.Button ({ label: 'Bigger' }); | ||||
| hbox.add (button); | ||||
| button.connect('clicked', function() { | ||||
|                    size *= 1.2; | ||||
|                    update_size (); | ||||
|                }); | ||||
|  | ||||
| stage.show(); | ||||
| Clutter.main(); | ||||
| stage.destroy(); | ||||
|  | ||||
							
								
								
									
										41
									
								
								tests/interactive/scrolling.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								tests/interactive/scrolling.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Nbtk = imports.gi.Nbtk; | ||||
|  | ||||
| const UI = imports.testcommon.ui; | ||||
|  | ||||
| UI.init(); | ||||
| let stage = Clutter.Stage.get_default(); | ||||
|  | ||||
| let vbox = new Nbtk.BoxLayout({ vertical: true, | ||||
|                                 width: stage.width, | ||||
|                                 height: stage.height, | ||||
|                                 style: "padding: 10px;" }); | ||||
| stage.add_actor(vbox); | ||||
|  | ||||
| let v = new Nbtk.ScrollView(); | ||||
| vbox.add(v, { expand: true }); | ||||
|  | ||||
| let b = new Nbtk.BoxLayout({ vertical: true, | ||||
|                              style: "border: 2px solid #880000; border-radius: 10px; padding: 0px 5px;" }); | ||||
| v.add_actor(b); | ||||
|  | ||||
| let cc_a = "a".charCodeAt(0); | ||||
| let s = ""; | ||||
| for (let i = 0; i < 26 * 3; i++) { | ||||
|     s += String.fromCharCode(cc_a + i % 26); | ||||
|  | ||||
|     let t = new Nbtk.Label({ text: s, | ||||
|                              reactive: true }); | ||||
|     let line = i + 1; | ||||
|     t.connect('button-press-event', | ||||
|               function() { | ||||
|                   log("Click on line " + line); | ||||
|               }); | ||||
|     b.add(t); | ||||
| } | ||||
|  | ||||
| stage.show(); | ||||
| Clutter.main(); | ||||
| stage.destroy(); | ||||
							
								
								
									
										48
									
								
								tests/run-test.sh.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								tests/run-test.sh.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| usage() { | ||||
|     echo >&2 "Usage run-test.sh [-v|--verbose] <test_js>..." | ||||
|     exit 1 | ||||
| } | ||||
|  | ||||
| tests= | ||||
| verbose=false | ||||
| debug= | ||||
| for arg in $@ ; do | ||||
|     case $arg in | ||||
| 	-g|--debug) | ||||
| 	    debug="gdb --args" | ||||
| 	    ;; | ||||
| 	-v|--verbose) | ||||
| 	    verbose=true | ||||
| 	    ;; | ||||
| 	-*) | ||||
| 	    usage | ||||
| 	    ;; | ||||
| 	*) | ||||
| 	    tests="$tests $arg" | ||||
| 	    ;; | ||||
|     esac | ||||
| done | ||||
|  | ||||
| builddir=`dirname $0` | ||||
| builddir=`cd $builddir && pwd` | ||||
| srcdir=$builddir/@srcdir@ | ||||
| srcdir=`cd $srcdir && pwd` | ||||
|  | ||||
| GI_TYPELIB_PATH="@MUTTER_LIB_DIR@/mutter:$builddir/../src" | ||||
| GJS_DEBUG_OUTPUT=stderr | ||||
| $verbose || GJS_DEBUG_TOPICS="JS ERROR;JS LOG" | ||||
| GNOME_SHELL_TESTSDIR="$srcdir/" | ||||
| LD_PRELOAD="$builddir/../src/.libs/libgnome-shell.so" | ||||
|  | ||||
| export GI_TYPELIB_PATH GJS_DEBUG_OUTPUT GJS_DEBUG_TOPICS GNOME_SHELL_JS GNOME_SHELL_TESTSDIR LD_PRELOAD | ||||
|  | ||||
| gjs_args= | ||||
| for i in $srcdir $srcdir/../js @GJS_JS_DIR@ @GJS_JS_NATIVE_DIR@ ; do | ||||
|     gjs_args="$gjs_args -I $i" | ||||
| done | ||||
|  | ||||
| for test in $tests ; do | ||||
|     $debug gjs-console $gjs_args $test || exit $? | ||||
| done | ||||
							
								
								
									
										
											BIN
										
									
								
								tests/testcommon/border-image.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/testcommon/border-image.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 981 B | 
							
								
								
									
										53
									
								
								tests/testcommon/test.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								tests/testcommon/test.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| @import "../../data/theme/gnome-shell.css"; | ||||
|  | ||||
| stage { | ||||
|     font: 16pt serif; | ||||
| } | ||||
|  | ||||
| .red { | ||||
|     background-color: red; | ||||
| } | ||||
|  | ||||
| .green { | ||||
|     background-color: green; | ||||
| } | ||||
|  | ||||
| .blue { | ||||
|     background-color: blue; | ||||
| } | ||||
|  | ||||
| .bold { | ||||
|     font-weight: bold; | ||||
| } | ||||
|  | ||||
| .italic { | ||||
|     font-style: italic; | ||||
| } | ||||
|  | ||||
| .big { | ||||
|     font-size: 150%; | ||||
| } | ||||
|  | ||||
| .monospace { | ||||
|     font-family: monospace; | ||||
| } | ||||
|  | ||||
| .border-image { | ||||
|     border: 15px; | ||||
|     border-image: url('border-image.png') 16; | ||||
| } | ||||
|  | ||||
| NbtkButton { | ||||
|     background: #eeddbb; | ||||
|     border: 1px solid black; | ||||
|     border-radius: 8px; | ||||
|     padding: 5px; | ||||
| } | ||||
|  | ||||
| NbtkButton:hover { | ||||
|     background: #ffeecc; | ||||
| } | ||||
|  | ||||
| NbtkButton:active { | ||||
|     background: #ccbb99; | ||||
| } | ||||
							
								
								
									
										19
									
								
								tests/testcommon/ui.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tests/testcommon/ui.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Nbtk = imports.gi.Nbtk; | ||||
| const Shell = imports.gi.Shell; | ||||
|  | ||||
| const Environment = imports.ui.environment; | ||||
|  | ||||
| function init() { | ||||
|     Clutter.init(null, null); | ||||
|     Environment.init(); | ||||
|  | ||||
|     let stage = Clutter.Stage.get_default(); | ||||
|     let context = Shell.ThemeContext.get_for_stage (stage); | ||||
|     let stylesheetPath = GLib.getenv("GNOME_SHELL_TESTSDIR") + "/testcommon/test.css"; | ||||
|     let theme = new Shell.Theme ({ application_stylesheet: stylesheetPath }); | ||||
|     context.set_theme (theme); | ||||
| } | ||||
| @@ -7,6 +7,8 @@ | ||||
|       href="git://git.clutter-project.org/"/> | ||||
|   <repository type="git" name="git.gnome.org" | ||||
|       href="git://git.gnome.org/"/> | ||||
|   <repository type="git" name="git.moblin.org" | ||||
|       href="git://git.moblin.org"/> | ||||
|  | ||||
|   <autotools id="gobject-introspection"> | ||||
|     <branch repo="git.gnome.org" module="gobject-introspection"/> | ||||
| @@ -36,6 +38,13 @@ | ||||
|     </dependencies> | ||||
|   </autotools> | ||||
|  | ||||
|   <autotools id="clutter-imcontext"> | ||||
|     <branch repo="git.moblin.org" module="clutter-imcontext"/> | ||||
|     <dependencies> | ||||
|         <dep package="clutter"/> | ||||
|     </dependencies> | ||||
|   </autotools> | ||||
|  | ||||
|   <autotools id="gconf" autogenargs="--disable-defaults-service"> | ||||
|     <branch repo="git.gnome.org" module="gconf"/> | ||||
|   </autotools> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user