Compare commits
	
		
			33 Commits
		
	
	
		
			gnome-3-12
			...
			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/gnome-shell | ||||||
| src/test-recorder | src/test-recorder | ||||||
| src/test-recorder.ogg | src/test-recorder.ogg | ||||||
|  | src/test-theme | ||||||
| stamp-h1 | stamp-h1 | ||||||
|  | tests/run-test.sh | ||||||
| xmldocs.make | 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 =		\ | EXTRA_DIST =		\ | ||||||
| 	.project	\ | 	.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: | distcheck-hook: | ||||||
| 	@echo "Checking disted javascript against files in git" | 	@echo "Checking disted files against files in git" | ||||||
| 	@failed=false; \ | 	@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 \ | 		if ! test -e $(distdir)/$$f ; then \ | ||||||
| 			echo File missing from distribution: $$f ; \ | 			echo File missing from distribution: $$f ; \ | ||||||
| 			failed=true ; \ | 			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 |                                  gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0 | ||||||
|                                  gobject-introspection-1.0 >= 0.6.5) |                                  gobject-introspection-1.0 >= 0.6.5) | ||||||
| PKG_CHECK_MODULES(TIDY, clutter-1.0) | 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(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0) | ||||||
| PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-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) | PKG_CHECK_MODULES(TRAY, gtk+-2.0) | ||||||
|  |  | ||||||
| MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin | MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin | ||||||
| @@ -128,5 +130,6 @@ AC_OUTPUT([ | |||||||
|   js/misc/Makefile |   js/misc/Makefile | ||||||
|   js/ui/Makefile |   js/ui/Makefile | ||||||
|   src/Makefile |   src/Makefile | ||||||
|  |   tests/Makefile | ||||||
|   po/Makefile.in |   po/Makefile.in | ||||||
| ]) | ]) | ||||||
|   | |||||||
| @@ -12,18 +12,26 @@ gnome-shell.desktop.in: gnome-shell.desktop.in.in | |||||||
| gnome-shell.desktop: gnome-shell.desktop.in | gnome-shell.desktop: gnome-shell.desktop.in | ||||||
| 	$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@ | 	$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@ | ||||||
|  |  | ||||||
| imagedir = $(pkgdatadir)/images | imagesdir = $(pkgdatadir)/images | ||||||
|  | dist_images_DATA =				\ | ||||||
| dist_image_DATA =		\ | 	add-workspace.svg			\ | ||||||
| 	add-workspace.svg	\ | 	app-well-glow.png			\ | ||||||
| 	app-well-glow.png	\ | 	back.svg				\ | ||||||
|         back.svg                \ | 	close.svg				\ | ||||||
| 	close.svg		\ | 	close-black.svg				\ | ||||||
| 	close-black.svg       \ | 	info.svg				\ | ||||||
| 	info.svg		\ | 	magnifier.svg				\ | ||||||
| 	magnifier.svg  \ |  | ||||||
| 	remove-workspace.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@ | schemadir  = @GCONF_SCHEMA_FILE_DIR@ | ||||||
| schema_DATA = gnome-shell.schemas | 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			\ | 	dash.js			\ | ||||||
| 	dnd.js			\ | 	dnd.js			\ | ||||||
| 	docDisplay.js		\ | 	docDisplay.js		\ | ||||||
|  | 	environment.js		\ | ||||||
| 	genericDisplay.js	\ | 	genericDisplay.js	\ | ||||||
| 	link.js			\ | 	link.js			\ | ||||||
| 	lookingGlass.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 Clutter = imports.gi.Clutter; | ||||||
| const Gio = imports.gi.Gio; | const Gio = imports.gi.Gio; | ||||||
| const Pango = imports.gi.Pango; | const Pango = imports.gi.Pango; | ||||||
|  | const Nbtk = imports.gi.Nbtk; | ||||||
| const Shell = imports.gi.Shell; | const Shell = imports.gi.Shell; | ||||||
| const Signals = imports.signals; | const Signals = imports.signals; | ||||||
| const Lang = imports.lang; | const Lang = imports.lang; | ||||||
| @@ -12,18 +13,7 @@ const Mainloop = imports.mainloop; | |||||||
| const Tweener = imports.ui.tweener; | const Tweener = imports.ui.tweener; | ||||||
| const Main = imports.ui.main; | const Main = imports.ui.main; | ||||||
|  |  | ||||||
| const LG_BORDER_COLOR = new Clutter.Color(); | /* Imports...feel free to add here as needed */ | ||||||
| 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 */ |  | ||||||
| var commandHeader = "const Clutter = imports.gi.Clutter; " + | var commandHeader = "const Clutter = imports.gi.Clutter; " + | ||||||
|                     "const GLib = imports.gi.GLib; " + |                     "const GLib = imports.gi.GLib; " + | ||||||
|                     "const Gtk = imports.gi.Gtk; " + |                     "const Gtk = imports.gi.Gtk; " + | ||||||
| @@ -47,7 +37,7 @@ function Notebook() { | |||||||
|  |  | ||||||
| Notebook.prototype = { | Notebook.prototype = { | ||||||
|     _init: function() { |     _init: function() { | ||||||
|         this.actor = new Big.Box(); |         this.actor = new Nbtk.BoxLayout({ vertical: true }); | ||||||
|  |  | ||||||
|         this.tabControls = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, |         this.tabControls = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, | ||||||
|                                          spacing: 4, padding: 2 }); |                                          spacing: 4, padding: 2 }); | ||||||
| @@ -58,21 +48,24 @@ Notebook.prototype = { | |||||||
|  |  | ||||||
|     appendPage: function(name, child) { |     appendPage: function(name, child) { | ||||||
|         let labelOuterBox = new Big.Box({ padding: 2 }); |         let labelOuterBox = new Big.Box({ padding: 2 }); | ||||||
|         let labelBox = new Big.Box({ padding: 2, border_color: MATRIX_GREEN, |         let labelBox = new Nbtk.BoxLayout({ reactive: true }); | ||||||
|                                      reactive: true }); |  | ||||||
|         labelOuterBox.append(labelBox, Big.BoxPackFlags.NONE); |         labelOuterBox.append(labelBox, Big.BoxPackFlags.NONE); | ||||||
|         let label = new Clutter.Text({ color: MATRIX_GREEN, |         let label = new Nbtk.Label({ text: name }); | ||||||
|                                        font_name: MATRIX_FONT, |  | ||||||
|                                        text: name }); |  | ||||||
|         labelBox.connect('button-press-event', Lang.bind(this, function () { |         labelBox.connect('button-press-event', Lang.bind(this, function () { | ||||||
|             this.selectChild(child); |             this.selectChild(child); | ||||||
|             return true; |             return true; | ||||||
|         })); |         })); | ||||||
|         labelBox.append(label, Big.BoxPackFlags.EXPAND); |         labelBox.add(label, { expand: true }); | ||||||
|         this._tabs.push([child, labelBox]); |  | ||||||
|         child.hide(); |  | ||||||
|         this.actor.append(child, Big.BoxPackFlags.EXPAND); |  | ||||||
|         this.tabControls.append(labelOuterBox, Big.BoxPackFlags.NONE); |         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) |         if (this._selectedIndex == -1) | ||||||
|             this.selectIndex(0); |             this.selectIndex(0); | ||||||
|     }, |     }, | ||||||
| @@ -80,10 +73,10 @@ Notebook.prototype = { | |||||||
|     _unselect: function() { |     _unselect: function() { | ||||||
|         if (this._selectedIndex < 0) |         if (this._selectedIndex < 0) | ||||||
|             return; |             return; | ||||||
|         let [child, labelBox] = this._tabs[this._selectedIndex]; |         let [child, labelBox, scrollview] = this._tabs[this._selectedIndex]; | ||||||
|         labelBox.padding = 2; |         labelBox.padding = 2; | ||||||
|         labelBox.border = 0; |         labelBox.border = 0; | ||||||
|         child.hide(); |         scrollview.hide(); | ||||||
|         this._selectedIndex = -1; |         this._selectedIndex = -1; | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
| @@ -95,10 +88,10 @@ Notebook.prototype = { | |||||||
|             this.emit('selection', null); |             this.emit('selection', null); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         let [child, labelBox] = this._tabs[index]; |         let [child, labelBox, scrollview] = this._tabs[index]; | ||||||
|         labelBox.padding = 1; |         labelBox.padding = 1; | ||||||
|         labelBox.border = 1; |         labelBox.border = 1; | ||||||
|         child.show(); |         scrollview.show(); | ||||||
|         this._selectedIndex = index; |         this._selectedIndex = index; | ||||||
|         this.emit('selection', child); |         this.emit('selection', child); | ||||||
|     }, |     }, | ||||||
| @@ -108,7 +101,7 @@ Notebook.prototype = { | |||||||
|             this.selectIndex(-1); |             this.selectIndex(-1); | ||||||
|         else { |         else { | ||||||
|             for (let i = 0; i < this._tabs.length; i++) { |             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) { |                 if (tabChild == child) { | ||||||
|                     this.selectIndex(i); |                     this.selectIndex(i); | ||||||
|                     return; |                     return; | ||||||
| @@ -130,20 +123,19 @@ Result.prototype = { | |||||||
|  |  | ||||||
|         this.actor = new Big.Box(); |         this.actor = new Big.Box(); | ||||||
|  |  | ||||||
|         let cmdTxt = new Clutter.Text({ color: MATRIX_GREEN, |         let cmdTxt = new Nbtk.Label({ text: command }); | ||||||
|                                         font_name: MATRIX_FONT, |         cmdTxt.ellipsize = Pango.EllipsizeMode.END; | ||||||
|                                         ellipsize: Pango.EllipsizeMode.END, |  | ||||||
|                                         text: command }); |  | ||||||
|         this.actor.append(cmdTxt, Big.BoxPackFlags.NONE); |         this.actor.append(cmdTxt, Big.BoxPackFlags.NONE); | ||||||
|         let resultTxt = new Clutter.Text({ color: MATRIX_GREEN, |         let resultTxt = new Nbtk.Label({ text: "r(" + index + ") = " + o }); | ||||||
|                                            font_name: MATRIX_FONT, |         resultTxt.ellipsize = Pango.EllipsizeMode.END; | ||||||
|                                            ellipsize: Pango.EllipsizeMode.END, |  | ||||||
|                                            text: "r(" + index + ") = " + o }); |  | ||||||
|         this.actor.append(resultTxt, Big.BoxPackFlags.NONE); |         this.actor.append(resultTxt, Big.BoxPackFlags.NONE); | ||||||
|         let line = new Big.Box({ border_color: GREY, |         let line = new Clutter.Rectangle({ name: "Separator", | ||||||
|                                  border_bottom: 1, |                                            height: 1 }); | ||||||
|                                  height: 8 }); |         let padBin = new Nbtk.Bin({ name: "Separator", x_fill: true, y_fill: true }); | ||||||
|         this.actor.append(line, Big.BoxPackFlags.NONE); |         padBin.add_actor(line); | ||||||
|  |         this.actor.append(padBin, Big.BoxPackFlags.NONE); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -158,17 +150,14 @@ ActorHierarchy.prototype = { | |||||||
|  |  | ||||||
|         this._parentList = []; |         this._parentList = []; | ||||||
|  |  | ||||||
|         this.actor = new Big.Box({ spacing: 4, |         this.actor = new Nbtk.BoxLayout({ name: "ActorHierarchy", vertical: true }); | ||||||
|                                    border: 1, |  | ||||||
|                                    padding: 4, |  | ||||||
|                                    border_color: GREY }); |  | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     setTarget: function(actor) { |     setTarget: function(actor) { | ||||||
|         this._previousTarget = this._target; |         this._previousTarget = this._target; | ||||||
|         this.target = actor; |         this.target = actor; | ||||||
|  |  | ||||||
|         this.actor.remove_all(); |         this.actor.get_children().forEach(function (child) { child.destroy(); }); | ||||||
|  |  | ||||||
|         if (!(actor instanceof Clutter.Actor)) |         if (!(actor instanceof Clutter.Actor)) | ||||||
|             return; |             return; | ||||||
| @@ -181,11 +170,9 @@ ActorHierarchy.prototype = { | |||||||
|         while ((parent = parent.get_parent()) != null) { |         while ((parent = parent.get_parent()) != null) { | ||||||
|             this._parentList.push(parent); |             this._parentList.push(parent); | ||||||
|  |  | ||||||
|             let link = new Clutter.Text({ color: MATRIX_GREEN, |             let link = new Nbtk.Label({ reactive: true, | ||||||
|                                           font_name: MATRIX_FONT, |                                         text: "" + parent }); | ||||||
|                                           reactive: true, |             this.actor.add_actor(link); | ||||||
|                                           text: "" + parent }); |  | ||||||
|             this.actor.append(link, Big.BoxPackFlags.IF_FITS); |  | ||||||
|             let parentTarget = parent; |             let parentTarget = parent; | ||||||
|             link.connect('button-press-event', Lang.bind(this, function () { |             link.connect('button-press-event', Lang.bind(this, function () { | ||||||
|                 this._selectByActor(parentTarget); |                 this._selectByActor(parentTarget); | ||||||
| @@ -214,16 +201,13 @@ PropertyInspector.prototype = { | |||||||
|  |  | ||||||
|         this._parentList = []; |         this._parentList = []; | ||||||
|  |  | ||||||
|         this.actor = new Big.Box({ spacing: 4, |         this.actor = new Nbtk.BoxLayout({ name: "PropertyInspector", vertical: true }); | ||||||
|                                    border: 1, |  | ||||||
|                                    padding: 4, |  | ||||||
|                                    border_color: GREY }); |  | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     setTarget: function(actor) { |     setTarget: function(actor) { | ||||||
|         this.target = actor; |         this.target = actor; | ||||||
|  |  | ||||||
|         this.actor.remove_all(); |         this.actor.get_children().forEach(function (child) { child.destroy(); }); | ||||||
|  |  | ||||||
|         for (let propName in actor) { |         for (let propName in actor) { | ||||||
|             let valueStr; |             let valueStr; | ||||||
| @@ -233,11 +217,9 @@ PropertyInspector.prototype = { | |||||||
|                 valueStr = '<error>'; |                 valueStr = '<error>'; | ||||||
|             } |             } | ||||||
|             let propText = propName + ": " + valueStr; |             let propText = propName + ": " + valueStr; | ||||||
|             let propDisplay = new Clutter.Text({ color: MATRIX_GREEN, |             let propDisplay = new Nbtk.Label({ reactive: true, | ||||||
|                                                  font_name: MATRIX_FONT, |                                                text: propText }); | ||||||
|                                                  reactive: true, |             this.actor.add_actor(propDisplay); | ||||||
|                                                  text: propText }); |  | ||||||
|             this.actor.append(propDisplay, Big.BoxPackFlags.IF_FITS); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -249,20 +231,16 @@ function Inspector() { | |||||||
| Inspector.prototype = { | Inspector.prototype = { | ||||||
|     _init: function() { |     _init: function() { | ||||||
|         let width = 150; |         let width = 150; | ||||||
|         let eventHandler = new Big.Box({ background_color: LG_BACKGROUND_COLOR, |         let eventHandler = new Nbtk.BoxLayout({ name: "LookingGlassDialog", | ||||||
|                                          border: 1, |                                                 vertical: false, | ||||||
|                                          border_color: LG_BORDER_COLOR, |                                                 y: Math.floor(global.stage.height/2), | ||||||
|                                          corner_radius: 4, |                                                 reactive: true }); | ||||||
|                                          y: global.stage.height/2, |  | ||||||
|                                          reactive: true |  | ||||||
|                                       }); |  | ||||||
|         eventHandler.connect('notify::allocation', Lang.bind(this, function () { |         eventHandler.connect('notify::allocation', Lang.bind(this, function () { | ||||||
|             eventHandler.x = Math.floor((global.stage.width)/2 - (eventHandler.width)/2); |             eventHandler.x = Math.floor((global.stage.width)/2 - (eventHandler.width)/2); | ||||||
|         })); |         })); | ||||||
|         global.stage.add_actor(eventHandler); |         global.stage.add_actor(eventHandler); | ||||||
|         let displayText = new Clutter.Text({ color: MATRIX_GREEN, |         let displayText = new Nbtk.Label(); | ||||||
|                                              font_name: MATRIX_FONT, text: '' }); |         eventHandler.add(displayText, { expand: true }); | ||||||
|         eventHandler.append(displayText, Big.BoxPackFlags.EXPAND); |  | ||||||
|  |  | ||||||
|         let borderPaintTarget = null; |         let borderPaintTarget = null; | ||||||
|         let borderPaintId = null; |         let borderPaintId = null; | ||||||
| @@ -321,29 +299,26 @@ LookingGlass.prototype = { | |||||||
|         this._offset = 0; |         this._offset = 0; | ||||||
|         this._results = []; |         this._results = []; | ||||||
|  |  | ||||||
|         // TODO replace with scrolling or something better |         // Sort of magic, but...eh. | ||||||
|         this._maxItems = 10; |         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); |         global.stage.add_actor(this.actor); | ||||||
|  |  | ||||||
|         let toolbar = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, |         let toolbar = new Nbtk.BoxLayout({ name: "Toolbar" }); | ||||||
|                                     border: 1, border_color: GREY, |         this.actor.add_actor(toolbar); | ||||||
|                                     corner_radius: 4 }); |  | ||||||
|         this.actor.append(toolbar, Big.BoxPackFlags.NONE); |  | ||||||
|         let inspectIcon = Shell.TextureCache.get_default().load_gicon(new Gio.ThemedIcon({ name: 'gtk-color-picker' }), |         let inspectIcon = Shell.TextureCache.get_default().load_gicon(new Gio.ThemedIcon({ name: 'gtk-color-picker' }), | ||||||
|                                                                       24); |                                                                       24); | ||||||
|         toolbar.append(inspectIcon, Big.BoxPackFlags.NONE); |         toolbar.add_actor(inspectIcon); | ||||||
|         inspectIcon.reactive = true; |         inspectIcon.reactive = true; | ||||||
|         inspectIcon.connect('button-press-event', Lang.bind(this, function () { |         inspectIcon.connect('button-press-event', Lang.bind(this, function () { | ||||||
|             let inspector = new Inspector(); |             let inspector = new Inspector(); | ||||||
| @@ -361,31 +336,26 @@ LookingGlass.prototype = { | |||||||
|         })); |         })); | ||||||
|  |  | ||||||
|         let notebook = new Notebook(); |         let notebook = new Notebook(); | ||||||
|         this.actor.append(notebook.actor, Big.BoxPackFlags.EXPAND); |         this.actor.add(notebook.actor, { expand: true }); | ||||||
|         toolbar.append(notebook.tabControls, Big.BoxPackFlags.END); |  | ||||||
|  |  | ||||||
|         this._evalBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, |         let emptyBox = new Nbtk.Bin(); | ||||||
|                                       spacing: 4 }); |         toolbar.add(emptyBox, { expand: true }); | ||||||
|  |         toolbar.add_actor(notebook.tabControls); | ||||||
|  |  | ||||||
|  |         this._evalBox = new Nbtk.BoxLayout({ name: "EvalBox", vertical: true }); | ||||||
|         notebook.appendPage('Evaluator', this._evalBox); |         notebook.appendPage('Evaluator', this._evalBox); | ||||||
|  |  | ||||||
|         this._resultsArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, |         this._resultsArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, | ||||||
|                                           spacing: 4 }); |                                           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 }); |         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, |         let label = new Nbtk.Label({ text: 'js>>> ' }); | ||||||
|                                        font_name: MATRIX_FONT, |  | ||||||
|                                        text: 'js>>> ' }); |  | ||||||
|         entryArea.append(label, Big.BoxPackFlags.NONE); |         entryArea.append(label, Big.BoxPackFlags.NONE); | ||||||
|  |  | ||||||
|         this._entry = new Clutter.Text({ color: MATRIX_GREEN, |         this._entry = new Nbtk.Entry(); | ||||||
|                                          font_name: MATRIX_FONT, |  | ||||||
|                                          editable: true, |  | ||||||
|                                          activatable: true, |  | ||||||
|                                          singleLineMode: true, |  | ||||||
|                                          text: ''}); |  | ||||||
|         /* unmapping the edit box will un-focus it, undo that */ |         /* unmapping the edit box will un-focus it, undo that */ | ||||||
|         notebook.connect('selection', Lang.bind(this, function (nb, child) { |         notebook.connect('selection', Lang.bind(this, function (nb, child) { | ||||||
|             if (child == this._evalBox) |             if (child == this._evalBox) | ||||||
| @@ -403,7 +373,7 @@ LookingGlass.prototype = { | |||||||
|             notebook.selectIndex(0); |             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(); |             let text = o.get_text(); | ||||||
|             // Ensure we don't get newlines in the command; the history file is |             // Ensure we don't get newlines in the command; the history file is | ||||||
|             // newline-separated. |             // newline-separated. | ||||||
| @@ -416,7 +386,7 @@ LookingGlass.prototype = { | |||||||
|             this._historyNavIndex = -1; |             this._historyNavIndex = -1; | ||||||
|             return true; |             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(); |             let symbol = e.get_key_symbol(); | ||||||
|             if (symbol == Clutter.Escape) { |             if (symbol == Clutter.Escape) { | ||||||
|                 this.close(); |                 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 () { |     _readHistory: function () { | ||||||
|         if (!this._historyFile.query_exists(null)) |         if (!this._historyFile.query_exists(null)) | ||||||
|             return; |             return; | ||||||
|   | |||||||
| @@ -7,16 +7,17 @@ const GLib = imports.gi.GLib; | |||||||
| const Lang = imports.lang; | const Lang = imports.lang; | ||||||
| const Mainloop = imports.mainloop; | const Mainloop = imports.mainloop; | ||||||
| const Meta = imports.gi.Meta; | const Meta = imports.gi.Meta; | ||||||
|  | const Nbtk = imports.gi.Nbtk; | ||||||
| const Shell = imports.gi.Shell; | const Shell = imports.gi.Shell; | ||||||
| const Signals = imports.signals; | const Signals = imports.signals; | ||||||
|  |  | ||||||
| const Chrome = imports.ui.chrome; | const Chrome = imports.ui.chrome; | ||||||
|  | const Environment = imports.ui.environment; | ||||||
| const Overview = imports.ui.overview; | const Overview = imports.ui.overview; | ||||||
| const Panel = imports.ui.panel; | const Panel = imports.ui.panel; | ||||||
| const RunDialog = imports.ui.runDialog; | const RunDialog = imports.ui.runDialog; | ||||||
| const LookingGlass = imports.ui.lookingGlass; | const LookingGlass = imports.ui.lookingGlass; | ||||||
| const Sidebar = imports.ui.sidebar; | const Sidebar = imports.ui.sidebar; | ||||||
| const Tweener = imports.ui.tweener; |  | ||||||
| const WindowManager = imports.ui.windowManager; | const WindowManager = imports.ui.windowManager; | ||||||
|  |  | ||||||
| const DEFAULT_BACKGROUND_COLOR = new Clutter.Color(); | const DEFAULT_BACKGROUND_COLOR = new Clutter.Color(); | ||||||
| @@ -43,7 +44,7 @@ function start() { | |||||||
|  |  | ||||||
|     global.grab_dbus_service(); |     global.grab_dbus_service(); | ||||||
|  |  | ||||||
|     Tweener.init(); |     Environment.init(); | ||||||
|  |  | ||||||
|     // Ensure ShellAppMonitor is initialized; this will |     // Ensure ShellAppMonitor is initialized; this will | ||||||
|     // also initialize ShellAppSystem first.  ShellAppSystem |     // also initialize ShellAppSystem first.  ShellAppSystem | ||||||
| @@ -66,6 +67,11 @@ function start() { | |||||||
|     for (let i = 0; i < children.length; i++) |     for (let i = 0; i < children.length; i++) | ||||||
|         children[i].destroy(); |         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) { |     global.connect('panel-run-dialog', function(panel) { | ||||||
|         // Make sure not more than one run dialog is shown. |         // Make sure not more than one run dialog is shown. | ||||||
|         getRunDialog().open(); |         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 = | EXTRA_DIST = | ||||||
| libexec_PROGRAMS = | libexec_PROGRAMS = | ||||||
| noinst_LTLIBRARIES = | noinst_LTLIBRARIES = | ||||||
|  | noinst_PROGRAMS = | ||||||
|  |  | ||||||
| .AUTOPARALLEL: | .AUTOPARALLEL: | ||||||
|  |  | ||||||
| @@ -24,6 +25,8 @@ EXTRA_DIST += gnome-shell.in | |||||||
|  |  | ||||||
| include Makefile-big.am | include Makefile-big.am | ||||||
| include Makefile-gdmuser.am | include Makefile-gdmuser.am | ||||||
|  | include Makefile-nbtk.am | ||||||
|  | include Makefile-toolkit.am | ||||||
| include Makefile-tray.am | include Makefile-tray.am | ||||||
|  |  | ||||||
| gnome_shell_cflags =				\ | gnome_shell_cflags =				\ | ||||||
| @@ -96,7 +99,7 @@ libgnome_shell_la_SOURCES =			\ | |||||||
| 	shell-wm.c				\ | 	shell-wm.c				\ | ||||||
| 	shell-wm.h | 	shell-wm.h | ||||||
|  |  | ||||||
| non_gir_sources =						\ | non_gir_sources =				\ | ||||||
| 	shell-embedded-window-private.h | 	shell-embedded-window-private.h | ||||||
|  |  | ||||||
| shell_recorder_sources =        \ | shell_recorder_sources =        \ | ||||||
| @@ -114,7 +117,7 @@ if BUILD_RECORDER | |||||||
| libgnome_shell_la_SOURCES += $(shell_recorder_sources) | libgnome_shell_la_SOURCES += $(shell_recorder_sources) | ||||||
| non_gir_sources += $(shell_recorder_non_gir_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_CPPFLAGS = $(TEST_SHELL_RECORDER_CFLAGS) | ||||||
| test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS) | test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS) | ||||||
| @@ -125,7 +128,7 @@ test_recorder_SOURCES =     \ | |||||||
| endif BUILD_RECORDER | endif BUILD_RECORDER | ||||||
|  |  | ||||||
| libgnome_shell_la_gir_sources = \ | 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 | shell-marshal.h: stamp-shell-marshal.h | ||||||
| 	@true | 	@true | ||||||
| @@ -152,14 +155,16 @@ libgnome_shell_la_LIBADD =	\ | |||||||
| 	$(MUTTER_PLUGIN_LIBS)	\ | 	$(MUTTER_PLUGIN_LIBS)	\ | ||||||
|         $(LIBGNOMEUI_LIBS)      \ |         $(LIBGNOMEUI_LIBS)      \ | ||||||
| 	libbig-1.0.la		\ | 	libbig-1.0.la		\ | ||||||
|  | 	libnbtk-1.0.la       	\ | ||||||
| 	libgdmuser-1.0.la	\ | 	libgdmuser-1.0.la	\ | ||||||
|  | 	libshell-toolkit.la	\ | ||||||
| 	libtray.la | 	libtray.la | ||||||
| libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags) | libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags) | ||||||
|  |  | ||||||
| typelibdir = $(pkglibdir) | 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)			\ | 	$(AM_V_GEN) $(G_IR_SCANNER)			\ | ||||||
| 		--namespace=Shell			\ | 		--namespace=Shell			\ | ||||||
| 		--nsversion=0.1				\ | 		--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)"    \ | 		--libtool="$(LIBTOOL)"    \ | ||||||
| 		--add-include-path=$(builddir)     \ | 		--add-include-path=$(builddir)     \ | ||||||
| 		--include=Big-1.0     \ | 		--include=Big-1.0     \ | ||||||
|  | 		--include=Nbtk-1.0     \ | ||||||
| 		--program=mutter			\ | 		--program=mutter			\ | ||||||
| 	        --program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \ | 	        --program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \ | ||||||
| 		$(addprefix $(srcdir)/,$(libgnome_shell_la_gir_sources)) \ | 		$(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 | # 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) | # (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 | 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)						\ | 		$(G_IR_COMPILER)						\ | ||||||
| 			--includedir=.						\ | 			--includedir=.						\ | ||||||
| 			--includedir=$(MUTTER_LIB_DIR)/mutter/			\ | 			--includedir=$(MUTTER_LIB_DIR)/mutter/			\ | ||||||
| 		Shell-0.1.gir -o $@ | 		Shell-0.1.gir -o $@ | ||||||
| CLEANFILES += Shell-0.1.typelib | 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)			\ | 	$(AM_V_GEN) $(G_IR_SCANNER)			\ | ||||||
| 		--namespace=Big				\ | 		--namespace=Big				\ | ||||||
| 		--nsversion=1.0				\ | 		--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 | CLEANFILES += Big-1.0.gir | ||||||
|  |  | ||||||
| Big-1.0.typelib: libbig-1.0.la 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} \ | 	$(AM_V_GEN) $(G_IR_COMPILER) Big-1.0.gir -o $@ | ||||||
| 		$(G_IR_COMPILER) Big-1.0.gir -o $@ |  | ||||||
| CLEANFILES += Big-1.0.typelib | 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; |     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 | static void | ||||||
| big_rectangle_update_corners(BigRectangle *rectangle) | big_rectangle_update_corners(BigRectangle *rectangle) | ||||||
| { | { | ||||||
| @@ -278,6 +324,7 @@ big_rectangle_update_corners(BigRectangle *rectangle) | |||||||
|     if (rectangle->radius != 0) { |     if (rectangle->radius != 0) { | ||||||
|         ClutterColor *color; |         ClutterColor *color; | ||||||
|         ClutterColor *border_color; |         ClutterColor *border_color; | ||||||
|  |         ClutterColor effective_border; | ||||||
|         guint border_width; |         guint border_width; | ||||||
|  |  | ||||||
|         g_object_get(rectangle, |         g_object_get(rectangle, | ||||||
| @@ -286,10 +333,12 @@ big_rectangle_update_corners(BigRectangle *rectangle) | |||||||
|                      "color", &color, |                      "color", &color, | ||||||
|                      NULL); |                      NULL); | ||||||
|  |  | ||||||
|  |         over (border_color, color, &effective_border); | ||||||
|  |  | ||||||
|         corner = corner_get(rectangle->radius, |         corner = corner_get(rectangle->radius, | ||||||
|                             color, |                             color, | ||||||
|                             border_width, |                             border_width, | ||||||
|                             border_color); |                             &effective_border); | ||||||
|  |  | ||||||
|         clutter_color_free(border_color); |         clutter_color_free(border_color); | ||||||
|         clutter_color_free(color); |         clutter_color_free(color); | ||||||
| @@ -329,12 +378,10 @@ big_rectangle_paint(ClutterActor *actor) | |||||||
|  |  | ||||||
|     rectangle = BIG_RECTANGLE(actor); |     rectangle = BIG_RECTANGLE(actor); | ||||||
|  |  | ||||||
|     if (rectangle->radius == 0) { |     /* We can't chain up, even when we the radius is 0, because of the different | ||||||
|         /* In that case we are no different than our parent class, |      * interpretation of the border/background relationship here than for | ||||||
|          * so don't bother */ |      * ClutterRectangle. | ||||||
|         CLUTTER_ACTOR_CLASS(big_rectangle_parent_class)->paint(actor); |      */ | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (rectangle->corners_dirty) |     if (rectangle->corners_dirty) | ||||||
|         big_rectangle_update_corners(rectangle); |         big_rectangle_update_corners(rectangle); | ||||||
| @@ -345,6 +392,9 @@ big_rectangle_paint(ClutterActor *actor) | |||||||
|                  "color", &color, |                  "color", &color, | ||||||
|                  NULL); |                  NULL); | ||||||
|  |  | ||||||
|  |     if (border_color->alpha == 0 && color->alpha == 0) | ||||||
|  |         goto out; | ||||||
|  |  | ||||||
|     actor_opacity = clutter_actor_get_paint_opacity (actor); |     actor_opacity = clutter_actor_get_paint_opacity (actor); | ||||||
|  |  | ||||||
|     clutter_actor_get_allocation_box(actor, &box); |     clutter_actor_get_allocation_box(actor, &box); | ||||||
| @@ -358,6 +408,11 @@ big_rectangle_paint(ClutterActor *actor) | |||||||
|  |  | ||||||
|     radius = rectangle->radius; |     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); |     max = MAX(border_width, radius); | ||||||
|  |  | ||||||
|     if (radius != 0) { |     if (radius != 0) { | ||||||
| @@ -393,33 +448,54 @@ big_rectangle_paint(ClutterActor *actor) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (border_width != 0) { |     if (border_width != 0) { | ||||||
|  |         ClutterColor effective_border; | ||||||
|  |         over (border_color, color, &effective_border); | ||||||
|  |  | ||||||
|         if (!rectangle->border_material) |         if (!rectangle->border_material) | ||||||
|             rectangle->border_material = cogl_material_new (); |             rectangle->border_material = cogl_material_new (); | ||||||
|  |  | ||||||
|         cogl_color_set_from_4ub(&tmp_color, |         cogl_color_set_from_4ub(&tmp_color, | ||||||
|                                 border_color->red, |                                 effective_border.red, | ||||||
|                                 border_color->green, |                                 effective_border.green, | ||||||
|                                 border_color->blue, |                                 effective_border.blue, | ||||||
|                                 actor_opacity * border_color->alpha / 255); |                                 actor_opacity * effective_border.alpha / 255); | ||||||
|         cogl_color_premultiply (&tmp_color); |         cogl_color_premultiply (&tmp_color); | ||||||
|         cogl_material_set_color(rectangle->border_material, &tmp_color); |         cogl_material_set_color(rectangle->border_material, &tmp_color); | ||||||
|         cogl_set_source(rectangle->border_material); |         cogl_set_source(rectangle->border_material); | ||||||
|  |  | ||||||
|         /* NORTH */ |         if (radius > 0) { /* skip corners */ | ||||||
|         cogl_rectangle(max, 0, |             /* NORTH */ | ||||||
|                        width - max, border_width); |             cogl_rectangle(max, 0, | ||||||
|  |                            width - max, border_width); | ||||||
|  |  | ||||||
|         /* EAST */ |             /* EAST */ | ||||||
|         cogl_rectangle(width - border_width, max, |             cogl_rectangle(width - border_width, max, | ||||||
|                        width, height - max); |                            width, height - max); | ||||||
|  |  | ||||||
|         /* SOUTH */ |             /* SOUTH */ | ||||||
|         cogl_rectangle(max, height - border_width, |             cogl_rectangle(max, height - border_width, | ||||||
|                        width - max, height); |                            width - max, height); | ||||||
|  |  | ||||||
|         /* WEST */ |             /* WEST */ | ||||||
|         cogl_rectangle(0, max, |             cogl_rectangle(0, max, | ||||||
|                        border_width, height - 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) |     if (!rectangle->background_material) | ||||||
| @@ -455,6 +531,7 @@ big_rectangle_paint(ClutterActor *actor) | |||||||
|     cogl_rectangle(border_width, max, |     cogl_rectangle(border_width, max, | ||||||
|                    width - border_width, height - max); |                    width - border_width, height - max); | ||||||
|  |  | ||||||
|  | out: | ||||||
|     clutter_color_free(border_color); |     clutter_color_free(border_color); | ||||||
|     clutter_color_free(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; |   MutterPlugin *plugin; | ||||||
|   ShellWM *wm; |   ShellWM *wm; | ||||||
|  |   const char *datadir; | ||||||
|   const char *imagedir; |   const char *imagedir; | ||||||
|   const char *configdir; |   const char *configdir; | ||||||
|  |  | ||||||
| @@ -57,6 +58,7 @@ enum { | |||||||
|   PROP_STAGE, |   PROP_STAGE, | ||||||
|   PROP_WINDOW_GROUP, |   PROP_WINDOW_GROUP, | ||||||
|   PROP_WINDOW_MANAGER, |   PROP_WINDOW_MANAGER, | ||||||
|  |   PROP_DATADIR, | ||||||
|   PROP_IMAGEDIR, |   PROP_IMAGEDIR, | ||||||
|   PROP_CONFIGDIR, |   PROP_CONFIGDIR, | ||||||
| }; | }; | ||||||
| @@ -128,6 +130,9 @@ shell_global_get_property(GObject         *object, | |||||||
|     case PROP_WINDOW_MANAGER: |     case PROP_WINDOW_MANAGER: | ||||||
|       g_value_set_object (value, global->wm); |       g_value_set_object (value, global->wm); | ||||||
|       break; |       break; | ||||||
|  |     case PROP_DATADIR: | ||||||
|  |       g_value_set_string (value, global->datadir); | ||||||
|  |       break; | ||||||
|     case PROP_IMAGEDIR: |     case PROP_IMAGEDIR: | ||||||
|       g_value_set_string (value, global->imagedir); |       g_value_set_string (value, global->imagedir); | ||||||
|       break; |       break; | ||||||
| @@ -149,6 +154,7 @@ shell_global_init (ShellGlobal *global) | |||||||
|  |  | ||||||
|   if (!datadir) |   if (!datadir) | ||||||
|     datadir = GNOME_SHELL_DATADIR; |     datadir = GNOME_SHELL_DATADIR; | ||||||
|  |   global->datadir = datadir; | ||||||
|  |  | ||||||
|   /* We make sure imagedir ends with a '/', since the JS won't have |   /* We make sure imagedir ends with a '/', since the JS won't have | ||||||
|    * access to g_build_filename() and so will end up just |    * access to g_build_filename() and so will end up just | ||||||
| @@ -254,6 +260,13 @@ shell_global_class_init (ShellGlobalClass *klass) | |||||||
|                                                         "Window management interface", |                                                         "Window management interface", | ||||||
|                                                         SHELL_TYPE_WM, |                                                         SHELL_TYPE_WM, | ||||||
|                                                         G_PARAM_READABLE)); |                                                         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, |   g_object_class_install_property (gobject_class, | ||||||
|                                    PROP_IMAGEDIR, |                                    PROP_IMAGEDIR, | ||||||
|                                    g_param_spec_string ("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/"/> |       href="git://git.clutter-project.org/"/> | ||||||
|   <repository type="git" name="git.gnome.org" |   <repository type="git" name="git.gnome.org" | ||||||
|       href="git://git.gnome.org/"/> |       href="git://git.gnome.org/"/> | ||||||
|  |   <repository type="git" name="git.moblin.org" | ||||||
|  |       href="git://git.moblin.org"/> | ||||||
|  |  | ||||||
|   <autotools id="gobject-introspection"> |   <autotools id="gobject-introspection"> | ||||||
|     <branch repo="git.gnome.org" module="gobject-introspection"/> |     <branch repo="git.gnome.org" module="gobject-introspection"/> | ||||||
| @@ -36,6 +38,13 @@ | |||||||
|     </dependencies> |     </dependencies> | ||||||
|   </autotools> |   </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"> |   <autotools id="gconf" autogenargs="--disable-defaults-service"> | ||||||
|     <branch repo="git.gnome.org" module="gconf"/> |     <branch repo="git.gnome.org" module="gconf"/> | ||||||
|   </autotools> |   </autotools> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user