Compare commits
	
		
			39 Commits
		
	
	
		
			wip/exalm/
			...
			shell-tool
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 83f37da1c1 | ||
|   | c2706add36 | ||
|   | 0a187b7222 | ||
|   | 3abe92d15d | ||
|   | 45b4d0384c | ||
|   | 083eed140c | ||
|   | 1283f0b160 | ||
|   | 3bbdc1e1e1 | ||
|   | 25f1246b6f | ||
|   | a37c86636b | ||
|   | 4057cfaa17 | ||
|   | 76443e91cd | ||
|   | d3c4c1f5ed | ||
|   | 040ddf077c | ||
|   | f313d38458 | ||
|   | 304b48a15d | ||
|   | d92b1d8da2 | ||
|   | df3ac4b25e | ||
|   | 0ce05a04c8 | ||
|   | c1c4adda02 | ||
|   | 595242c389 | ||
|   | 7e678ef0d2 | ||
|   | ebbf304899 | ||
|   | 2077485827 | ||
|   | 0c0a0c66e2 | ||
|   | 2412a89445 | ||
|   | 789e268264 | ||
|   | 7507d10223 | ||
|   | b18a8ebcae | ||
|   | ed07413c20 | ||
|   | f94eab803b | ||
|   | 0315a6e4a8 | ||
|   | 48085dd428 | ||
|   | 099b73a0c4 | ||
|   | b8d46422d5 | ||
|   | 459bdfba78 | ||
|   | 66414ea3f6 | ||
|   | d453067e24 | ||
|   | ae320a26fc | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -38,5 +38,7 @@ src/gnomeshell-taskpanel | ||||
| src/gnome-shell | ||||
| src/test-recorder | ||||
| src/test-recorder.ogg | ||||
| src/test-theme | ||||
| stamp-h1 | ||||
| tests/run-test.sh | ||||
| xmldocs.make | ||||
|   | ||||
							
								
								
									
										17
									
								
								Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								Makefile.am
									
									
									
									
									
								
							| @@ -1,13 +1,22 @@ | ||||
| SUBDIRS = data js src po | ||||
| SUBDIRS = data js src tests po | ||||
|  | ||||
| EXTRA_DIST =		\ | ||||
| 	.project	\ | ||||
| 	.settings | ||||
| 	.settings	\ | ||||
| 	autogen.sh | ||||
|  | ||||
| # These are files checked into Git that we don't want to distribute | ||||
| DIST_EXCLUDE =					\ | ||||
| 	.gitignore				\ | ||||
| 	gnome-shell.doap			\ | ||||
| 	MAINTAINERS				\ | ||||
| 	tools/build/* | ||||
|  | ||||
| distcheck-hook: | ||||
| 	@echo "Checking disted javascript against files in git" | ||||
| 	@echo "Checking disted files against files in git" | ||||
| 	@failed=false; \ | ||||
| 	for f in `cd $(srcdir) && git ls-files js` ; do \ | ||||
| 	exclude=`(for p in $(DIST_EXCLUDE) ; do echo --exclude=$$p ; done)`; \ | ||||
| 	for f in `cd $(srcdir) && git ls-files $$exclude` ; do \ | ||||
| 		if ! test -e $(distdir)/$$f ; then \ | ||||
| 			echo File missing from distribution: $$f ; \ | ||||
| 			failed=true ; \ | ||||
|   | ||||
| @@ -57,6 +57,7 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugin | ||||
|                                  gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0 | ||||
|                                  gobject-introspection-1.0 >= 0.6.5) | ||||
| PKG_CHECK_MODULES(TIDY, clutter-1.0) | ||||
| PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 clutter-imcontext-0.1 libcroco-0.6) | ||||
| 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(TRAY, gtk+-2.0) | ||||
| @@ -128,5 +129,6 @@ AC_OUTPUT([ | ||||
|   js/misc/Makefile | ||||
|   js/ui/Makefile | ||||
|   src/Makefile | ||||
|   tests/Makefile | ||||
|   po/Makefile.in | ||||
| ]) | ||||
|   | ||||
| @@ -12,18 +12,26 @@ gnome-shell.desktop.in: gnome-shell.desktop.in.in | ||||
| gnome-shell.desktop: gnome-shell.desktop.in | ||||
| 	$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@ | ||||
|  | ||||
| imagedir = $(pkgdatadir)/images | ||||
|  | ||||
| dist_image_DATA =		\ | ||||
| 	add-workspace.svg	\ | ||||
| 	app-well-glow.png	\ | ||||
|         back.svg                \ | ||||
| 	close.svg		\ | ||||
| 	close-black.svg       \ | ||||
| 	info.svg		\ | ||||
| 	magnifier.svg  \ | ||||
| imagesdir = $(pkgdatadir)/images | ||||
| dist_images_DATA =				\ | ||||
| 	add-workspace.svg			\ | ||||
| 	app-well-glow.png			\ | ||||
| 	back.svg				\ | ||||
| 	close.svg				\ | ||||
| 	close-black.svg				\ | ||||
| 	info.svg				\ | ||||
| 	magnifier.svg				\ | ||||
| 	remove-workspace.svg | ||||
|  | ||||
| themedir = $(pkgdatadir)/theme | ||||
| dist_theme_DATA =				\ | ||||
| 	theme/gnome-shell.css			\ | ||||
| 	theme/scroll-button-down.png		\ | ||||
| 	theme/scroll-button-down-hover.png	\ | ||||
| 	theme/scroll-button-up.png		\ | ||||
| 	theme/scroll-button-up-hover.png	\ | ||||
| 	theme/scroll-vhandle.png | ||||
|  | ||||
| schemadir  = @GCONF_SCHEMA_FILE_DIR@ | ||||
| schema_DATA = gnome-shell.schemas | ||||
|  | ||||
|   | ||||
							
								
								
									
										97
									
								
								data/theme/gnome-shell.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								data/theme/gnome-shell.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| /* Copyright 2009, Red Hat, Inc. | ||||
|  * | ||||
|  * Portions adapted from Mx'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. | ||||
|  */ | ||||
|  | ||||
| StScrollBar | ||||
| { | ||||
|   background-color: #354761; | ||||
|   padding: 0px; | ||||
| } | ||||
|  | ||||
| StScrollView | ||||
| { | ||||
|   scrollbar-width: 16px; | ||||
|   scrollbar-height: 16px; | ||||
| } | ||||
|  | ||||
| StButton#up-stepper | ||||
| { | ||||
|   border-image: url("scroll-button-up.png") 5; | ||||
| } | ||||
|  | ||||
| StButton#up-stepper:hover, | ||||
| StButton#up-stepper:active | ||||
| { | ||||
|   border-image: url("scroll-button-up-hover.png") 5; | ||||
| } | ||||
|  | ||||
| StButton#down-stepper | ||||
| { | ||||
|   border-image: url("scroll-button-down.png") 5; | ||||
| } | ||||
|  | ||||
| StButton#down-stepper:hover, | ||||
| StButton#down-stepper:active | ||||
| { | ||||
|   border-image: url("scroll-button-down-hover.png") 5; | ||||
| } | ||||
|  | ||||
| StScrollBar StButton#vhandle | ||||
| { | ||||
|   border-image: url("scroll-vhandle.png") 5; | ||||
| } | ||||
|  | ||||
| StScrollBar StButton#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 StLabel | ||||
| { | ||||
|   color: #88ff66; | ||||
| } | ||||
|  | ||||
| #LookingGlassDialog StEntry | ||||
| { | ||||
|   color: #88ff66; | ||||
| } | ||||
|  | ||||
| #LookingGlassDialog StBoxLayout#EvalBox | ||||
| { | ||||
|   padding: 4px; | ||||
|   spacing: 4px; | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-down-hover.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/theme/scroll-button-down-hover.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 225 B | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-down.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/theme/scroll-button-down.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 225 B | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-up-hover.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/theme/scroll-button-up-hover.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 211 B | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-button-up.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/theme/scroll-button-up.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 211 B | 
							
								
								
									
										
											BIN
										
									
								
								data/theme/scroll-vhandle.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/theme/scroll-vhandle.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 323 B | 
| @@ -9,6 +9,7 @@ dist_jsui_DATA =		\ | ||||
| 	dash.js			\ | ||||
| 	dnd.js			\ | ||||
| 	docDisplay.js		\ | ||||
| 	environment.js		\ | ||||
| 	genericDisplay.js	\ | ||||
| 	lightbox.js		\ | ||||
| 	link.js			\ | ||||
|   | ||||
							
								
								
									
										33
									
								
								js/ui/environment.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								js/ui/environment.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| 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(St.BoxLayout); | ||||
| _patchContainerClass(St.Table); | ||||
|  | ||||
| function init() { | ||||
|     Tweener.init(); | ||||
| } | ||||
| @@ -4,6 +4,7 @@ const Big = imports.gi.Big; | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Gio = imports.gi.Gio; | ||||
| const Pango = imports.gi.Pango; | ||||
| const St = imports.gi.St; | ||||
| const Shell = imports.gi.Shell; | ||||
| const Signals = imports.signals; | ||||
| const Lang = imports.lang; | ||||
| @@ -12,18 +13,7 @@ const Mainloop = imports.mainloop; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const Main = imports.ui.main; | ||||
|  | ||||
| const LG_BORDER_COLOR = new Clutter.Color(); | ||||
| LG_BORDER_COLOR.from_pixel(0x0000aca0); | ||||
| const LG_BACKGROUND_COLOR = new Clutter.Color(); | ||||
| LG_BACKGROUND_COLOR.from_pixel(0x000000d5); | ||||
| const GREY = new Clutter.Color(); | ||||
| GREY.from_pixel(0xAFAFAFFF); | ||||
| const MATRIX_GREEN = new Clutter.Color(); | ||||
| MATRIX_GREEN.from_pixel(0x88ff66ff); | ||||
| // FIXME pull from GConf | ||||
| const MATRIX_FONT = 'Monospace 10'; | ||||
|  | ||||
|                     /* Imports...feel free to add here as needed */ | ||||
| /* Imports...feel free to add here as needed */ | ||||
| var commandHeader = "const Clutter = imports.gi.Clutter; " + | ||||
|                     "const GLib = imports.gi.GLib; " + | ||||
|                     "const Gtk = imports.gi.Gtk; " + | ||||
| @@ -47,7 +37,7 @@ function Notebook() { | ||||
|  | ||||
| Notebook.prototype = { | ||||
|     _init: function() { | ||||
|         this.actor = new Big.Box(); | ||||
|         this.actor = new St.BoxLayout({ vertical: true }); | ||||
|  | ||||
|         this.tabControls = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, | ||||
|                                          spacing: 4, padding: 2 }); | ||||
| @@ -58,21 +48,24 @@ Notebook.prototype = { | ||||
|  | ||||
|     appendPage: function(name, child) { | ||||
|         let labelOuterBox = new Big.Box({ padding: 2 }); | ||||
|         let labelBox = new Big.Box({ padding: 2, border_color: MATRIX_GREEN, | ||||
|                                      reactive: true }); | ||||
|         let labelBox = new St.BoxLayout({ reactive: true }); | ||||
|         labelOuterBox.append(labelBox, Big.BoxPackFlags.NONE); | ||||
|         let label = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                        font_name: MATRIX_FONT, | ||||
|                                        text: name }); | ||||
|         let label = new St.Label({ text: name }); | ||||
|         labelBox.connect('button-press-event', Lang.bind(this, function () { | ||||
|             this.selectChild(child); | ||||
|             return true; | ||||
|         })); | ||||
|         labelBox.append(label, Big.BoxPackFlags.EXPAND); | ||||
|         this._tabs.push([child, labelBox]); | ||||
|         child.hide(); | ||||
|         this.actor.append(child, Big.BoxPackFlags.EXPAND); | ||||
|         labelBox.add(label, { expand: true }); | ||||
|         this.tabControls.append(labelOuterBox, Big.BoxPackFlags.NONE); | ||||
|  | ||||
|         let scrollview = new St.ScrollView({ x_fill: true, y_fill: true }); | ||||
|         scrollview.get_hscroll_bar().hide(); | ||||
|         scrollview.add_actor(child); | ||||
|  | ||||
|         this._tabs.push([child, labelBox, scrollview]); | ||||
|         scrollview.hide(); | ||||
|         this.actor.add(scrollview, { expand: true }); | ||||
|  | ||||
|         if (this._selectedIndex == -1) | ||||
|             this.selectIndex(0); | ||||
|     }, | ||||
| @@ -80,10 +73,10 @@ Notebook.prototype = { | ||||
|     _unselect: function() { | ||||
|         if (this._selectedIndex < 0) | ||||
|             return; | ||||
|         let [child, labelBox] = this._tabs[this._selectedIndex]; | ||||
|         let [child, labelBox, scrollview] = this._tabs[this._selectedIndex]; | ||||
|         labelBox.padding = 2; | ||||
|         labelBox.border = 0; | ||||
|         child.hide(); | ||||
|         scrollview.hide(); | ||||
|         this._selectedIndex = -1; | ||||
|     }, | ||||
|  | ||||
| @@ -95,10 +88,10 @@ Notebook.prototype = { | ||||
|             this.emit('selection', null); | ||||
|             return; | ||||
|         } | ||||
|         let [child, labelBox] = this._tabs[index]; | ||||
|         let [child, labelBox, scrollview] = this._tabs[index]; | ||||
|         labelBox.padding = 1; | ||||
|         labelBox.border = 1; | ||||
|         child.show(); | ||||
|         scrollview.show(); | ||||
|         this._selectedIndex = index; | ||||
|         this.emit('selection', child); | ||||
|     }, | ||||
| @@ -108,7 +101,7 @@ Notebook.prototype = { | ||||
|             this.selectIndex(-1); | ||||
|         else { | ||||
|             for (let i = 0; i < this._tabs.length; i++) { | ||||
|                 let [tabChild, labelBox] = this._tabs[i]; | ||||
|                 let [tabChild, labelBox, scrollview] = this._tabs[i]; | ||||
|                 if (tabChild == child) { | ||||
|                     this.selectIndex(i); | ||||
|                     return; | ||||
| @@ -130,20 +123,19 @@ Result.prototype = { | ||||
|  | ||||
|         this.actor = new Big.Box(); | ||||
|  | ||||
|         let cmdTxt = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                         font_name: MATRIX_FONT, | ||||
|                                         ellipsize: Pango.EllipsizeMode.END, | ||||
|                                         text: command }); | ||||
|         let cmdTxt = new St.Label({ text: command }); | ||||
|         cmdTxt.ellipsize = Pango.EllipsizeMode.END; | ||||
|  | ||||
|         this.actor.append(cmdTxt, Big.BoxPackFlags.NONE); | ||||
|         let resultTxt = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                            font_name: MATRIX_FONT, | ||||
|                                            ellipsize: Pango.EllipsizeMode.END, | ||||
|                                            text: "r(" + index + ") = " + o }); | ||||
|         let resultTxt = new St.Label({ text: "r(" + index + ") = " + o }); | ||||
|         resultTxt.ellipsize = Pango.EllipsizeMode.END; | ||||
|  | ||||
|         this.actor.append(resultTxt, Big.BoxPackFlags.NONE); | ||||
|         let line = new Big.Box({ border_color: GREY, | ||||
|                                  border_bottom: 1, | ||||
|                                  height: 8 }); | ||||
|         this.actor.append(line, Big.BoxPackFlags.NONE); | ||||
|         let line = new Clutter.Rectangle({ name: "Separator", | ||||
|                                            height: 1 }); | ||||
|         let padBin = new St.Bin({ name: "Separator", x_fill: true, y_fill: true }); | ||||
|         padBin.add_actor(line); | ||||
|         this.actor.append(padBin, Big.BoxPackFlags.NONE); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -158,17 +150,14 @@ ActorHierarchy.prototype = { | ||||
|  | ||||
|         this._parentList = []; | ||||
|  | ||||
|         this.actor = new Big.Box({ spacing: 4, | ||||
|                                    border: 1, | ||||
|                                    padding: 4, | ||||
|                                    border_color: GREY }); | ||||
|         this.actor = new St.BoxLayout({ name: "ActorHierarchy", vertical: true }); | ||||
|     }, | ||||
|  | ||||
|     setTarget: function(actor) { | ||||
|         this._previousTarget = this._target; | ||||
|         this.target = actor; | ||||
|  | ||||
|         this.actor.remove_all(); | ||||
|         this.actor.get_children().forEach(function (child) { child.destroy(); }); | ||||
|  | ||||
|         if (!(actor instanceof Clutter.Actor)) | ||||
|             return; | ||||
| @@ -181,11 +170,9 @@ ActorHierarchy.prototype = { | ||||
|         while ((parent = parent.get_parent()) != null) { | ||||
|             this._parentList.push(parent); | ||||
|  | ||||
|             let link = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                           font_name: MATRIX_FONT, | ||||
|                                           reactive: true, | ||||
|                                           text: "" + parent }); | ||||
|             this.actor.append(link, Big.BoxPackFlags.IF_FITS); | ||||
|             let link = new St.Label({ reactive: true, | ||||
|                                       text: "" + parent }); | ||||
|             this.actor.add_actor(link); | ||||
|             let parentTarget = parent; | ||||
|             link.connect('button-press-event', Lang.bind(this, function () { | ||||
|                 this._selectByActor(parentTarget); | ||||
| @@ -214,16 +201,13 @@ PropertyInspector.prototype = { | ||||
|  | ||||
|         this._parentList = []; | ||||
|  | ||||
|         this.actor = new Big.Box({ spacing: 4, | ||||
|                                    border: 1, | ||||
|                                    padding: 4, | ||||
|                                    border_color: GREY }); | ||||
|         this.actor = new St.BoxLayout({ name: "PropertyInspector", vertical: true }); | ||||
|     }, | ||||
|  | ||||
|     setTarget: function(actor) { | ||||
|         this.target = actor; | ||||
|  | ||||
|         this.actor.remove_all(); | ||||
|         this.actor.get_children().forEach(function (child) { child.destroy(); }); | ||||
|  | ||||
|         for (let propName in actor) { | ||||
|             let valueStr; | ||||
| @@ -233,11 +217,9 @@ PropertyInspector.prototype = { | ||||
|                 valueStr = '<error>'; | ||||
|             } | ||||
|             let propText = propName + ": " + valueStr; | ||||
|             let propDisplay = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                                  font_name: MATRIX_FONT, | ||||
|                                                  reactive: true, | ||||
|                                                  text: propText }); | ||||
|             this.actor.append(propDisplay, Big.BoxPackFlags.IF_FITS); | ||||
|             let propDisplay = new St.Label({ reactive: true, | ||||
|                                              text: propText }); | ||||
|             this.actor.add_actor(propDisplay); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -249,20 +231,16 @@ function Inspector() { | ||||
| Inspector.prototype = { | ||||
|     _init: function() { | ||||
|         let width = 150; | ||||
|         let eventHandler = new Big.Box({ background_color: LG_BACKGROUND_COLOR, | ||||
|                                          border: 1, | ||||
|                                          border_color: LG_BORDER_COLOR, | ||||
|                                          corner_radius: 4, | ||||
|                                          y: global.stage.height/2, | ||||
|                                          reactive: true | ||||
|                                       }); | ||||
|         let eventHandler = new St.BoxLayout({ name: "LookingGlassDialog", | ||||
|                                               vertical: false, | ||||
|                                               y: Math.floor(global.stage.height/2), | ||||
|                                               reactive: true }); | ||||
|         eventHandler.connect('notify::allocation', Lang.bind(this, function () { | ||||
|             eventHandler.x = Math.floor((global.stage.width)/2 - (eventHandler.width)/2); | ||||
|         })); | ||||
|         global.stage.add_actor(eventHandler); | ||||
|         let displayText = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                              font_name: MATRIX_FONT, text: '' }); | ||||
|         eventHandler.append(displayText, Big.BoxPackFlags.EXPAND); | ||||
|         let displayText = new St.Label(); | ||||
|         eventHandler.add(displayText, { expand: true }); | ||||
|  | ||||
|         let borderPaintTarget = null; | ||||
|         let borderPaintId = null; | ||||
| @@ -321,29 +299,26 @@ LookingGlass.prototype = { | ||||
|         this._offset = 0; | ||||
|         this._results = []; | ||||
|  | ||||
|         // TODO replace with scrolling or something better | ||||
|         this._maxItems = 10; | ||||
|         // Sort of magic, but...eh. | ||||
|         this._maxItems = 150; | ||||
|  | ||||
|         this.actor = new St.BoxLayout({ name: "LookingGlassDialog", | ||||
|                                         vertical: true, | ||||
|                                         visible: false }); | ||||
|  | ||||
|         let gconf = Shell.GConf.get_default(); | ||||
|         gconf.watch_directory("/desktop/gnome/interface"); | ||||
|         gconf.connect("changed::/desktop/gnome/interface/monospace_font_name", | ||||
|                       Lang.bind(this, this._updateFont)); | ||||
|         this._updateFont(); | ||||
|  | ||||
|         this.actor = new Big.Box({ background_color: LG_BACKGROUND_COLOR, | ||||
|                                    border: 1, | ||||
|                                    border_color: LG_BORDER_COLOR, | ||||
|                                    corner_radius: 4, | ||||
|                                    padding_top: 8, | ||||
|                                    padding_left: 4, | ||||
|                                    padding_right: 4, | ||||
|                                    padding_bottom: 4, | ||||
|                                    spacing: 4, | ||||
|                                    visible: false | ||||
|                                 }); | ||||
|         global.stage.add_actor(this.actor); | ||||
|  | ||||
|         let toolbar = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, | ||||
|                                     border: 1, border_color: GREY, | ||||
|                                     corner_radius: 4 }); | ||||
|         this.actor.append(toolbar, Big.BoxPackFlags.NONE); | ||||
|         let toolbar = new St.BoxLayout({ name: "Toolbar" }); | ||||
|         this.actor.add_actor(toolbar); | ||||
|         let inspectIcon = Shell.TextureCache.get_default().load_gicon(new Gio.ThemedIcon({ name: 'gtk-color-picker' }), | ||||
|                                                                       24); | ||||
|         toolbar.append(inspectIcon, Big.BoxPackFlags.NONE); | ||||
|         toolbar.add_actor(inspectIcon); | ||||
|         inspectIcon.reactive = true; | ||||
|         inspectIcon.connect('button-press-event', Lang.bind(this, function () { | ||||
|             let inspector = new Inspector(); | ||||
| @@ -361,31 +336,26 @@ LookingGlass.prototype = { | ||||
|         })); | ||||
|  | ||||
|         let notebook = new Notebook(); | ||||
|         this.actor.append(notebook.actor, Big.BoxPackFlags.EXPAND); | ||||
|         toolbar.append(notebook.tabControls, Big.BoxPackFlags.END); | ||||
|         this.actor.add(notebook.actor, { expand: true }); | ||||
|  | ||||
|         this._evalBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, | ||||
|                                       spacing: 4 }); | ||||
|         let emptyBox = new St.Bin(); | ||||
|         toolbar.add(emptyBox, { expand: true }); | ||||
|         toolbar.add_actor(notebook.tabControls); | ||||
|  | ||||
|         this._evalBox = new St.BoxLayout({ name: "EvalBox", vertical: true }); | ||||
|         notebook.appendPage('Evaluator', this._evalBox); | ||||
|  | ||||
|         this._resultsArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL, | ||||
|                                           spacing: 4 }); | ||||
|         this._evalBox.append(this._resultsArea, Big.BoxPackFlags.EXPAND); | ||||
|         this._evalBox.add(this._resultsArea, { expand: true }); | ||||
|  | ||||
|         let entryArea = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL }); | ||||
|         this._evalBox.append(entryArea, Big.BoxPackFlags.NONE); | ||||
|         this._evalBox.add_actor(entryArea); | ||||
|  | ||||
|         let label = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                        font_name: MATRIX_FONT, | ||||
|                                        text: 'js>>> ' }); | ||||
|         let label = new St.Label({ text: 'js>>> ' }); | ||||
|         entryArea.append(label, Big.BoxPackFlags.NONE); | ||||
|  | ||||
|         this._entry = new Clutter.Text({ color: MATRIX_GREEN, | ||||
|                                          font_name: MATRIX_FONT, | ||||
|                                          editable: true, | ||||
|                                          activatable: true, | ||||
|                                          singleLineMode: true, | ||||
|                                          text: ''}); | ||||
|         this._entry = new St.Entry(); | ||||
|         /* unmapping the edit box will un-focus it, undo that */ | ||||
|         notebook.connect('selection', Lang.bind(this, function (nb, child) { | ||||
|             if (child == this._evalBox) | ||||
| @@ -403,7 +373,7 @@ LookingGlass.prototype = { | ||||
|             notebook.selectIndex(0); | ||||
|         })); | ||||
|  | ||||
|         this._entry.connect('activate', Lang.bind(this, function (o, e) { | ||||
|         this._entry.clutter_text.connect('activate', Lang.bind(this, function (o, e) { | ||||
|             let text = o.get_text(); | ||||
|             // Ensure we don't get newlines in the command; the history file is | ||||
|             // newline-separated. | ||||
| @@ -416,7 +386,7 @@ LookingGlass.prototype = { | ||||
|             this._historyNavIndex = -1; | ||||
|             return true; | ||||
|         })); | ||||
|         this._entry.connect('key-press-event', Lang.bind(this, function(o, e) { | ||||
|         this._entry.clutter_text.connect('key-press-event', Lang.bind(this, function(o, e) { | ||||
|             let symbol = e.get_key_symbol(); | ||||
|             if (symbol == Clutter.Escape) { | ||||
|                 this.close(); | ||||
| @@ -446,6 +416,19 @@ LookingGlass.prototype = { | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     _updateFont: function() { | ||||
|         let gconf = Shell.GConf.get_default(); | ||||
|         let fontName = gconf.get_string("/desktop/gnome/interface/monospace_font_name"); | ||||
|         // This is mishandled by the scanner - should by Pango.FontDescription_from_string(fontName); | ||||
|         // https://bugzilla.gnome.org/show_bug.cgi?id=595889 | ||||
|         let fontDesc = Pango.Font.description_from_string(fontName); | ||||
|         // We ignore everything but size and style; you'd be crazy to set your system-wide | ||||
|         // monospace font to be bold/oblique/etc. Could easily be added here. | ||||
|         this.actor.style = | ||||
|             'font-size: ' + fontDesc.get_size() / 1024. + (fontDesc.get_size_is_absolute() ? 'px' : 'pt') + ';' | ||||
|             + 'font-family: "' + fontDesc.get_family() + '";'; | ||||
|     }, | ||||
|  | ||||
|     _readHistory: function () { | ||||
|         if (!this._historyFile.query_exists(null)) | ||||
|             return; | ||||
|   | ||||
| @@ -10,15 +10,16 @@ const Mainloop = imports.mainloop; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Shell = imports.gi.Shell; | ||||
| const Signals = imports.signals; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const Chrome = imports.ui.chrome; | ||||
| const Environment = imports.ui.environment; | ||||
| const Overview = imports.ui.overview; | ||||
| const Panel = imports.ui.panel; | ||||
| const RunDialog = imports.ui.runDialog; | ||||
| const LookingGlass = imports.ui.lookingGlass; | ||||
| const ShellDBus = imports.ui.shellDBus; | ||||
| const Sidebar = imports.ui.sidebar; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const WindowManager = imports.ui.windowManager; | ||||
|  | ||||
| const DEFAULT_BACKGROUND_COLOR = new Clutter.Color(); | ||||
| @@ -52,7 +53,7 @@ function start() { | ||||
|     // back into sync ones. | ||||
|     DBus.session.flush(); | ||||
|  | ||||
|     Tweener.init(); | ||||
|     Environment.init(); | ||||
|  | ||||
|     // Ensure ShellAppMonitor is initialized; this will | ||||
|     // also initialize ShellAppSystem first.  ShellAppSystem | ||||
| @@ -75,6 +76,11 @@ function start() { | ||||
|     for (let i = 0; i < children.length; i++) | ||||
|         children[i].destroy(); | ||||
|  | ||||
|     let themeContext = St.ThemeContext.get_for_stage (global.stage); | ||||
|     let stylesheetPath = global.datadir + "/theme/gnome-shell.css"; | ||||
|     let theme = new St.Theme ({ application_stylesheet: stylesheetPath }); | ||||
|     themeContext.set_theme (theme); | ||||
|  | ||||
|     global.connect('panel-run-dialog', function(panel) { | ||||
|         // Make sure not more than one run dialog is shown. | ||||
|         getRunDialog().open(); | ||||
|   | ||||
							
								
								
									
										142
									
								
								src/Makefile-st.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								src/Makefile-st.am
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | ||||
| st_cflags =					\ | ||||
|     -I$(top_srcdir)/src				\ | ||||
|     -DPREFIX=\""$(prefix)"\"			\ | ||||
|     -DLIBDIR=\""$(libdir)"\"			\ | ||||
|     -DG_DISABLE_DEPRECATED			\ | ||||
|     -DG_LOG_DOMAIN=\"St\"			\ | ||||
|     -DST_COMPILATION				\ | ||||
|     -DPACKAGE_DATA_DIR=\"$(pkgdatadir)\"	\ | ||||
|     $(ST_CFLAGS)				\ | ||||
|     $(NULL) | ||||
|  | ||||
| st_built_sources =				\ | ||||
|     st-enum-types.h				\ | ||||
|     st-enum-types.c				\ | ||||
|     st-marshal.h				\ | ||||
|     st-marshal.c | ||||
|  | ||||
| BUILT_SOURCES += $(st_built_sources) | ||||
|  | ||||
| EXTRA_DIST +=					\ | ||||
| 	st/st-marshal.list			\ | ||||
| 	st/st-enum-types.h.in			\ | ||||
| 	st/st-enum-types.c.in | ||||
|  | ||||
| CLEANFILES += stamp-st-marshal.h stamp-st-enum-types.h | ||||
|  | ||||
| st-marshal.h: stamp-st-marshal.h | ||||
| 	@true | ||||
| stamp-st-marshal.h: Makefile st/st-marshal.list | ||||
| 	$(AM_V_GEN) $(GLIB_GENMARSHAL)					\ | ||||
| 		--prefix=_st_marshal					\ | ||||
| 		--header						\ | ||||
| 	$(srcdir)/st/st-marshal.list > $@.tmp &&			\ | ||||
| 	(cmp -s $@.tmp st-marshal.h || cp -f $@.tmp st-marshal.h) &&	\ | ||||
| 	rm -f $@.tmp &&							\ | ||||
| 	echo timestamp > $(@F) | ||||
|  | ||||
| st-marshal.c: Makefile st/st-marshal.list | ||||
| 	$(AM_V_GEN) (echo "#include \"st-marshal.h\"" ;	\ | ||||
| 	 $(GLIB_GENMARSHAL)				\ | ||||
| 		--prefix=_st_marshal			\ | ||||
| 		--body					\ | ||||
| 	 $(srcdir)/st/st-marshal.list ) > $@.tmp &&	\ | ||||
| 	cp -f $@.tmp st-marshal.c &&			\ | ||||
| 	rm -f $@.tmp | ||||
|  | ||||
| st-enum-types.h: stamp-st-enum-types.h Makefile | ||||
| 	@true | ||||
| stamp-st-enum-types.h: $(source_h) st/st-enum-types.h.in | ||||
| 	$(AM_V_GEN) ( cd $(srcdir) &&					\ | ||||
| 	  $(GLIB_MKENUMS)						\ | ||||
| 	    --template st/st-enum-types.h.in				\ | ||||
| 	  $(st_source_h) ) >> $@.tmp &&					\ | ||||
| 	(cmp -s $@.tmp st-enum-types.h || cp $@.tmp st-enum-types.h) &&	\ | ||||
| 	rm -f $@.tmp &&							\ | ||||
| 	echo timestamp > $(@F) | ||||
|  | ||||
| st-enum-types.c: stamp-st-enum-types.h st/st-enum-types.c.in | ||||
| 	$(AM_V_GEN) ( cd $(srcdir) &&		\ | ||||
| 	  $(GLIB_MKENUMS)			\ | ||||
| 	    --template st/st-enum-types.c.in	\ | ||||
| 	  $(st_source_h) ) >> $@.tmp &&		\ | ||||
| 	cp $@.tmp $@ &&				\ | ||||
| 	rm -f $@.tmp | ||||
|  | ||||
| # please, keep this sorted alphabetically | ||||
| st_source_h =					\ | ||||
|     st/st-adjustment.h				\ | ||||
|     st/st-bin.h					\ | ||||
|     st/st-border-image.h			\ | ||||
|     st/st-box-layout.h				\ | ||||
|     st/st-box-layout-child.h			\ | ||||
|     st/st-button.h				\ | ||||
|     st/st-clipboard.h				\ | ||||
|     st/st-entry.h				\ | ||||
|     st/st-label.h				\ | ||||
|     st/st-scrollable.h				\ | ||||
|     st/st-scroll-bar.h				\ | ||||
|     st/st-scroll-view.h				\ | ||||
|     st/st-subtexture.h				\ | ||||
|     st/st-table.h				\ | ||||
|     st/st-table-child.h				\ | ||||
|     st/st-texture-cache.h			\ | ||||
|     st/st-texture-frame.h			\ | ||||
|     st/st-theme.h				\ | ||||
|     st/st-theme-context.h			\ | ||||
|     st/st-theme-node.h				\ | ||||
|     st/st-tooltip.h				\ | ||||
|     st/st-types.h				\ | ||||
|     st/st-widget.h				\ | ||||
|     $(NULL) | ||||
|  | ||||
| st_source_private_h =				\ | ||||
|     st/st-private.h				\ | ||||
|     st/st-table-private.h			\ | ||||
|     st/st-theme-private.h | ||||
|  | ||||
| # please, keep this sorted alphabetically | ||||
| st_source_c =					\ | ||||
|     st/st-adjustment.c				\ | ||||
|     st/st-bin.c					\ | ||||
|     st/st-border-image.c			\ | ||||
|     st/st-box-layout.c				\ | ||||
|     st/st-box-layout-child.c			\ | ||||
|     st/st-button.c				\ | ||||
|     st/st-clipboard.c				\ | ||||
|     st/st-entry.c				\ | ||||
|     st/st-label.c				\ | ||||
|     st/st-private.c				\ | ||||
|     st/st-scrollable.c				\ | ||||
|     st/st-scroll-bar.c				\ | ||||
|     st/st-scroll-view.c				\ | ||||
|     st/st-subtexture.c				\ | ||||
|     st/st-table.c				\ | ||||
|     st/st-table-child.c				\ | ||||
|     st/st-texture-cache.c			\ | ||||
|     st/st-texture-frame.c			\ | ||||
|     st/st-theme.c				\ | ||||
|     st/st-theme-context.c			\ | ||||
|     st/st-theme-node.c				\ | ||||
|     st/st-tooltip.c				\ | ||||
|     st/st-widget.c				\ | ||||
|     $(NULL) | ||||
|  | ||||
| noinst_LTLIBRARIES += libst-1.0.la | ||||
|  | ||||
| libst_1_0_la_LIBADD = $(ST_LIBS) | ||||
| libst_1_0_la_SOURCES =				\ | ||||
|     $(st_source_c)				\ | ||||
|     $(st_source_private_c)			\ | ||||
|     $(st_source_h)				\ | ||||
|     $(st_built_sources)				\ | ||||
|     $(NULL) | ||||
| libst_1_0_la_CPPFLAGS = $(st_cflags) | ||||
| libst_1_0_la_LDFLAGS = $(LDADD) | ||||
|  | ||||
| noinst_PROGRAMS += test-theme | ||||
|  | ||||
| test_theme_CPPFLAGS = $(st_cflags) | ||||
| test_theme_LDADD = libst-1.0.la | ||||
|  | ||||
| test_theme_SOURCES = st/test-theme.c | ||||
| @@ -4,6 +4,7 @@ CLEANFILES = | ||||
| EXTRA_DIST = | ||||
| libexec_PROGRAMS = | ||||
| noinst_LTLIBRARIES = | ||||
| noinst_PROGRAMS = | ||||
|  | ||||
| .AUTOPARALLEL: | ||||
|  | ||||
| @@ -24,6 +25,7 @@ EXTRA_DIST += gnome-shell.in | ||||
|  | ||||
| include Makefile-big.am | ||||
| include Makefile-gdmuser.am | ||||
| include Makefile-st.am | ||||
| include Makefile-tray.am | ||||
|  | ||||
| gnome_shell_cflags =				\ | ||||
| @@ -94,7 +96,7 @@ libgnome_shell_la_SOURCES =			\ | ||||
| 	shell-wm.c				\ | ||||
| 	shell-wm.h | ||||
|  | ||||
| non_gir_sources =						\ | ||||
| non_gir_sources =				\ | ||||
| 	shell-embedded-window-private.h | ||||
|  | ||||
| shell_recorder_sources =        \ | ||||
| @@ -112,7 +114,7 @@ if BUILD_RECORDER | ||||
| libgnome_shell_la_SOURCES += $(shell_recorder_sources) | ||||
| non_gir_sources += $(shell_recorder_non_gir_sources) | ||||
|  | ||||
| noinst_PROGRAMS = test-recorder | ||||
| noinst_PROGRAMS += test-recorder | ||||
|  | ||||
| test_recorder_CPPFLAGS = $(TEST_SHELL_RECORDER_CFLAGS) | ||||
| test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS) | ||||
| @@ -150,14 +152,15 @@ libgnome_shell_la_LIBADD =	\ | ||||
| 	$(MUTTER_PLUGIN_LIBS)	\ | ||||
|         $(LIBGNOMEUI_LIBS)      \ | ||||
| 	libbig-1.0.la		\ | ||||
| 	libst-1.0.la       	\ | ||||
| 	libgdmuser-1.0.la	\ | ||||
| 	libtray.la | ||||
| libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags) | ||||
|  | ||||
| typelibdir = $(pkglibdir) | ||||
| typelib_DATA = Shell-0.1.typelib Big-1.0.typelib | ||||
| typelib_DATA = Shell-0.1.typelib Big-1.0.typelib St-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 St-1.0.gir libgnome-shell.la Makefile | ||||
| 	$(AM_V_GEN) $(G_IR_SCANNER)			\ | ||||
| 		--namespace=Shell			\ | ||||
| 		--nsversion=0.1				\ | ||||
| @@ -167,6 +170,7 @@ Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir libgnome-shell.la Makefile | ||||
| 		--libtool="$(LIBTOOL)"    \ | ||||
| 		--add-include-path=$(builddir)     \ | ||||
| 		--include=Big-1.0     \ | ||||
| 		--include=St-1.0     \ | ||||
| 		--program=mutter			\ | ||||
| 	        --program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \ | ||||
| 		$(addprefix $(srcdir)/,$(libgnome_shell_la_gir_sources)) \ | ||||
| @@ -177,14 +181,14 @@ CLEANFILES += Shell-0.1.gir | ||||
| # The dependency on libgnome-shell.la here is because g-ir-compiler opens it | ||||
| # (not the fake library, since we've already done the rewriting) | ||||
| Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir Big-1.0.gir | ||||
| 	$(AM_V_GEN) LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH}	\ | ||||
| 	$(AM_V_GEN) \ | ||||
| 		$(G_IR_COMPILER)						\ | ||||
| 			--includedir=.						\ | ||||
| 			--includedir=$(MUTTER_LIB_DIR)/mutter/			\ | ||||
| 		Shell-0.1.gir -o $@ | ||||
| CLEANFILES += Shell-0.1.typelib | ||||
|  | ||||
| Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la $(srcdir)/big-enum-types.h Makefile | ||||
| Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la Makefile | ||||
| 	$(AM_V_GEN) $(G_IR_SCANNER)			\ | ||||
| 		--namespace=Big				\ | ||||
| 		--nsversion=1.0				\ | ||||
| @@ -201,6 +205,28 @@ Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la $(srcdir) | ||||
| CLEANFILES += Big-1.0.gir | ||||
|  | ||||
| Big-1.0.typelib: libbig-1.0.la Big-1.0.gir | ||||
| 	$(AM_V_GEN) LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH} \ | ||||
| 		$(G_IR_COMPILER) Big-1.0.gir -o $@ | ||||
| 	$(AM_V_GEN) $(G_IR_COMPILER) Big-1.0.gir -o $@ | ||||
| CLEANFILES += Big-1.0.typelib | ||||
|  | ||||
| St-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libst-1.0.la Makefile | ||||
| 	$(AM_V_GEN) $(G_IR_SCANNER)						\ | ||||
| 	        --namespace=St							\ | ||||
| 	        --nsversion=1.0							\ | ||||
| 	        --include=Clutter-1.0						\ | ||||
| 		--add-include-path=$(builddir)     				\ | ||||
| 	        --libtool="$(LIBTOOL)"						\ | ||||
| 	        --program=mutter						\ | ||||
| 		--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la	\ | ||||
| 	        -DST_COMPILATION						\ | ||||
| 	        $(addprefix $(srcdir)/,$(st_source_h))				\ | ||||
| 	        $(addprefix $(srcdir)/,$(st_source_c))				\ | ||||
| 	        $(srcdir)/st-enum-types.h					\ | ||||
| 	        $(ST_CFLAGS)							\ | ||||
| 	        -o $@ | ||||
| CLEANFILES += St-1.0.gir | ||||
|  | ||||
| St-1.0.typelib: St-1.0.gir | ||||
| 	$(AM_V_GEN) $(G_IR_COMPILER)						\ | ||||
| 		$< -o $@ | ||||
|  | ||||
| CLEANFILES += St-1.0.typelib | ||||
|   | ||||
| @@ -268,6 +268,52 @@ corner_get(guint         radius, | ||||
|     return corner; | ||||
| } | ||||
|  | ||||
| /* To match the CSS specification, we want the border to look like it was | ||||
|  * drawn over the background. But actually drawing the border over the | ||||
|  * background will produce slightly bad antialiasing at the edges, so | ||||
|  * compute the effective border color instead. | ||||
|  */ | ||||
| #define NORM(x) (t = (x) + 127, (t + (t >> 8)) >> 8) | ||||
| #define MULT(c,a) NORM(c*a) | ||||
|  | ||||
| static void | ||||
| premultiply (ClutterColor *color) | ||||
| { | ||||
|     guint t; | ||||
|     color->red = MULT (color->red, color->alpha); | ||||
|     color->green = MULT (color->green, color->alpha); | ||||
|     color->blue = MULT (color->blue, color->alpha); | ||||
| } | ||||
|  | ||||
| static void | ||||
| unpremultiply (ClutterColor *color) | ||||
| { | ||||
|     if (color->alpha != 0) { | ||||
|         color->red = (color->red * 255 + 127) / color->alpha; | ||||
|         color->green = (color->green * 255 + 127) / color->alpha; | ||||
|         color->blue = (color->blue * 255 + 127) / color->alpha; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| over (const ClutterColor *source, | ||||
|       const ClutterColor *destination, | ||||
|       ClutterColor       *result) | ||||
| { | ||||
|     guint t; | ||||
|     ClutterColor src = *source; | ||||
|     ClutterColor dst = *destination; | ||||
|     premultiply (&src); | ||||
|     premultiply (&dst); | ||||
|  | ||||
|     result->alpha = src.alpha + NORM ((255 - src.alpha) * dst.alpha); | ||||
|     result->red   = src.red +   NORM ((255 - src.alpha) * dst.red); | ||||
|     result->green = src.green + NORM ((255 - src.alpha) * dst.green); | ||||
|     result->blue  = src.blue +  NORM ((255 - src.alpha) * dst.blue); | ||||
|  | ||||
|     unpremultiply (result); | ||||
| } | ||||
|  | ||||
| static void | ||||
| big_rectangle_update_corners(BigRectangle *rectangle) | ||||
| { | ||||
| @@ -278,6 +324,7 @@ big_rectangle_update_corners(BigRectangle *rectangle) | ||||
|     if (rectangle->radius != 0) { | ||||
|         ClutterColor *color; | ||||
|         ClutterColor *border_color; | ||||
|         ClutterColor effective_border; | ||||
|         guint border_width; | ||||
|  | ||||
|         g_object_get(rectangle, | ||||
| @@ -286,10 +333,12 @@ big_rectangle_update_corners(BigRectangle *rectangle) | ||||
|                      "color", &color, | ||||
|                      NULL); | ||||
|  | ||||
|         over (border_color, color, &effective_border); | ||||
|  | ||||
|         corner = corner_get(rectangle->radius, | ||||
|                             color, | ||||
|                             border_width, | ||||
|                             border_color); | ||||
|                             &effective_border); | ||||
|  | ||||
|         clutter_color_free(border_color); | ||||
|         clutter_color_free(color); | ||||
| @@ -329,12 +378,10 @@ big_rectangle_paint(ClutterActor *actor) | ||||
|  | ||||
|     rectangle = BIG_RECTANGLE(actor); | ||||
|  | ||||
|     if (rectangle->radius == 0) { | ||||
|         /* In that case we are no different than our parent class, | ||||
|          * so don't bother */ | ||||
|         CLUTTER_ACTOR_CLASS(big_rectangle_parent_class)->paint(actor); | ||||
|         return; | ||||
|     } | ||||
|     /* We can't chain up, even when we the radius is 0, because of the different | ||||
|      * interpretation of the border/background relationship here than for | ||||
|      * ClutterRectangle. | ||||
|      */ | ||||
|  | ||||
|     if (rectangle->corners_dirty) | ||||
|         big_rectangle_update_corners(rectangle); | ||||
| @@ -345,6 +392,9 @@ big_rectangle_paint(ClutterActor *actor) | ||||
|                  "color", &color, | ||||
|                  NULL); | ||||
|  | ||||
|     if (border_color->alpha == 0 && color->alpha == 0) | ||||
|         goto out; | ||||
|  | ||||
|     actor_opacity = clutter_actor_get_paint_opacity (actor); | ||||
|  | ||||
|     clutter_actor_get_allocation_box(actor, &box); | ||||
| @@ -358,6 +408,11 @@ big_rectangle_paint(ClutterActor *actor) | ||||
|  | ||||
|     radius = rectangle->radius; | ||||
|  | ||||
|     /* Optimization; if the border is transparent, it just looks like part of | ||||
|      * the background */ | ||||
|     if (radius == 0 && border_color->alpha == 0) | ||||
|         border_width = 0; | ||||
|  | ||||
|     max = MAX(border_width, radius); | ||||
|  | ||||
|     if (radius != 0) { | ||||
| @@ -393,33 +448,54 @@ big_rectangle_paint(ClutterActor *actor) | ||||
|     } | ||||
|  | ||||
|     if (border_width != 0) { | ||||
|         ClutterColor effective_border; | ||||
|         over (border_color, color, &effective_border); | ||||
|  | ||||
|         if (!rectangle->border_material) | ||||
|             rectangle->border_material = cogl_material_new (); | ||||
|  | ||||
|         cogl_color_set_from_4ub(&tmp_color, | ||||
|                                 border_color->red, | ||||
|                                 border_color->green, | ||||
|                                 border_color->blue, | ||||
|                                 actor_opacity * border_color->alpha / 255); | ||||
|                                 effective_border.red, | ||||
|                                 effective_border.green, | ||||
|                                 effective_border.blue, | ||||
|                                 actor_opacity * effective_border.alpha / 255); | ||||
|         cogl_color_premultiply (&tmp_color); | ||||
|         cogl_material_set_color(rectangle->border_material, &tmp_color); | ||||
|         cogl_set_source(rectangle->border_material); | ||||
|  | ||||
|         /* NORTH */ | ||||
|         cogl_rectangle(max, 0, | ||||
|                        width - max, border_width); | ||||
|         if (radius > 0) { /* skip corners */ | ||||
|             /* NORTH */ | ||||
|             cogl_rectangle(max, 0, | ||||
|                            width - max, border_width); | ||||
|  | ||||
|         /* EAST */ | ||||
|         cogl_rectangle(width - border_width, max, | ||||
|                        width, height - max); | ||||
|             /* EAST */ | ||||
|             cogl_rectangle(width - border_width, max, | ||||
|                            width, height - max); | ||||
|  | ||||
|         /* SOUTH */ | ||||
|         cogl_rectangle(max, height - border_width, | ||||
|                        width - max, height); | ||||
|             /* SOUTH */ | ||||
|             cogl_rectangle(max, height - border_width, | ||||
|                            width - max, height); | ||||
|  | ||||
|         /* WEST */ | ||||
|         cogl_rectangle(0, max, | ||||
|                        border_width, height - max); | ||||
|             /* WEST */ | ||||
|             cogl_rectangle(0, max, | ||||
|                            border_width, height - max); | ||||
|         } else { /* include corners */ | ||||
|             /* NORTH */ | ||||
|             cogl_rectangle(0, 0, | ||||
|                            width, border_width); | ||||
|  | ||||
|             /* EAST */ | ||||
|             cogl_rectangle(width - border_width, border_width, | ||||
|                            width, height - border_width); | ||||
|  | ||||
|             /* SOUTH */ | ||||
|             cogl_rectangle(0, height - border_width, | ||||
|                            width, height); | ||||
|  | ||||
|             /* WEST */ | ||||
|             cogl_rectangle(0, border_width, | ||||
|                            border_width, height - border_width); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!rectangle->background_material) | ||||
| @@ -455,6 +531,7 @@ big_rectangle_paint(ClutterActor *actor) | ||||
|     cogl_rectangle(border_width, max, | ||||
|                    width - border_width, height - max); | ||||
|  | ||||
| out: | ||||
|     clutter_color_free(border_color); | ||||
|     clutter_color_free(color); | ||||
| } | ||||
|   | ||||
| @@ -1,64 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #include <mutter-plugin.h> | ||||
|  | ||||
| ClutterActor * | ||||
| mutter_plugin_get_overlay_group (MutterPlugin *plugin) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| ClutterActor * | ||||
| mutter_plugin_get_stage (MutterPlugin *plugin) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| GList * | ||||
| mutter_plugin_get_windows (MutterPlugin *plugin) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| void | ||||
| mutter_plugin_query_screen_size (MutterPlugin *plugin, | ||||
|                                  int          *width, | ||||
|                                  int          *height) | ||||
| { | ||||
| } | ||||
|  | ||||
| void | ||||
| mutter_plugin_set_stage_input_area (MutterPlugin *plugin, | ||||
|                                     gint x, gint y, gint width, gint height) | ||||
| { | ||||
| } | ||||
|  | ||||
| MetaScreen * | ||||
| mutter_plugin_get_screen (MutterPlugin *plugin) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| ClutterActor * | ||||
| mutter_plugin_get_window_group (MutterPlugin *plugin) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| Display * | ||||
| meta_display_get_xdisplay (MetaDisplay *display) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| MetaDisplay * | ||||
| meta_screen_get_display (MetaScreen *display) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| Window | ||||
| meta_screen_get_xroot (MetaScreen *display) | ||||
| { | ||||
|   return None; | ||||
| } | ||||
| @@ -40,6 +40,7 @@ struct _ShellGlobal { | ||||
|    | ||||
|   MutterPlugin *plugin; | ||||
|   ShellWM *wm; | ||||
|   const char *datadir; | ||||
|   const char *imagedir; | ||||
|   const char *configdir; | ||||
|  | ||||
| @@ -57,6 +58,7 @@ enum { | ||||
|   PROP_STAGE, | ||||
|   PROP_WINDOW_GROUP, | ||||
|   PROP_WINDOW_MANAGER, | ||||
|   PROP_DATADIR, | ||||
|   PROP_IMAGEDIR, | ||||
|   PROP_CONFIGDIR, | ||||
| }; | ||||
| @@ -128,6 +130,9 @@ shell_global_get_property(GObject         *object, | ||||
|     case PROP_WINDOW_MANAGER: | ||||
|       g_value_set_object (value, global->wm); | ||||
|       break; | ||||
|     case PROP_DATADIR: | ||||
|       g_value_set_string (value, global->datadir); | ||||
|       break; | ||||
|     case PROP_IMAGEDIR: | ||||
|       g_value_set_string (value, global->imagedir); | ||||
|       break; | ||||
| @@ -149,6 +154,7 @@ shell_global_init (ShellGlobal *global) | ||||
|  | ||||
|   if (!datadir) | ||||
|     datadir = GNOME_SHELL_DATADIR; | ||||
|   global->datadir = datadir; | ||||
|  | ||||
|   /* We make sure imagedir ends with a '/', since the JS won't have | ||||
|    * access to g_build_filename() and so will end up just | ||||
| @@ -254,6 +260,13 @@ shell_global_class_init (ShellGlobalClass *klass) | ||||
|                                                         "Window management interface", | ||||
|                                                         SHELL_TYPE_WM, | ||||
|                                                         G_PARAM_READABLE)); | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_DATADIR, | ||||
|                                    g_param_spec_string ("datadir", | ||||
|                                                         "Data directory", | ||||
|                                                         "Directory containing gnome-shell data files", | ||||
|                                                         NULL, | ||||
|                                                         G_PARAM_READABLE)); | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_IMAGEDIR, | ||||
|                                    g_param_spec_string ("imagedir", | ||||
|   | ||||
| @@ -1,240 +0,0 @@ | ||||
| #include "shell-panel-window.h" | ||||
|  | ||||
| #include <gdk/gdkx.h> | ||||
| #include <X11/Xlib.h> | ||||
|  | ||||
| #define PANEL_HEIGHT 25 | ||||
|  | ||||
| enum { | ||||
|    PROP_0, | ||||
|  | ||||
| }; | ||||
|  | ||||
| static void shell_panel_window_finalize (GObject *object); | ||||
| static void shell_panel_window_size_request (GtkWidget *self, GtkRequisition *req); | ||||
| static void shell_panel_window_size_allocate (GtkWidget *self, GtkAllocation *allocation); | ||||
| static void shell_panel_window_realize (GtkWidget *self); | ||||
| static void shell_panel_window_show (GtkWidget *self); | ||||
| static void set_strut (ShellPanelWindow *self); | ||||
| static void on_workarea_changed (ShellPanelWindow *self); | ||||
| static void handle_new_workarea (ShellPanelWindow *self); | ||||
| static GdkFilterReturn filter_func (GdkXEvent *xevent, | ||||
| 				    GdkEvent *event, | ||||
| 				    gpointer data); | ||||
|  | ||||
| G_DEFINE_TYPE(ShellPanelWindow, shell_panel_window, GTK_TYPE_WINDOW); | ||||
|  | ||||
| struct ShellPanelWindowPrivate { | ||||
|   GtkAllocation workarea; | ||||
|   guint width; | ||||
|   guint height; | ||||
|   Atom workarea_atom; | ||||
| }; | ||||
|  | ||||
| static void | ||||
| shell_panel_window_class_init(ShellPanelWindowClass *klass) | ||||
| { | ||||
|     GObjectClass *gobject_class = (GObjectClass *)klass; | ||||
|     GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; | ||||
|  | ||||
|     gobject_class->finalize = shell_panel_window_finalize; | ||||
|      | ||||
|     widget_class->realize = shell_panel_window_realize; | ||||
|     widget_class->size_request = shell_panel_window_size_request;     | ||||
|     widget_class->size_allocate = shell_panel_window_size_allocate; | ||||
|     widget_class->show = shell_panel_window_show; | ||||
| } | ||||
|  | ||||
| static void shell_panel_window_init (ShellPanelWindow *self) | ||||
| { | ||||
|   self->priv = g_new0 (ShellPanelWindowPrivate, 1); | ||||
|  | ||||
|   self->priv->workarea_atom = gdk_x11_get_xatom_by_name_for_display (gdk_display_get_default (), "_NET_WORKAREA"); | ||||
|    | ||||
|   gtk_window_set_type_hint (GTK_WINDOW (self), GDK_WINDOW_TYPE_HINT_DOCK); | ||||
|   gtk_window_set_focus_on_map (GTK_WINDOW (self), FALSE); | ||||
|   gdk_window_add_filter (NULL, filter_func, self); | ||||
| } | ||||
|  | ||||
| static void shell_panel_window_finalize (GObject *object) | ||||
| { | ||||
|     ShellPanelWindow *self = (ShellPanelWindow*)object; | ||||
|  | ||||
|     g_free (self->priv); | ||||
|     g_signal_handlers_destroy(object); | ||||
|     G_OBJECT_CLASS (shell_panel_window_parent_class)->finalize(object); | ||||
| } | ||||
|  | ||||
| ShellPanelWindow* shell_panel_window_new(void) { | ||||
|     return (ShellPanelWindow*) g_object_new(SHELL_TYPE_PANEL_WINDOW,  | ||||
|         "type", GTK_WINDOW_TOPLEVEL, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_strut (ShellPanelWindow *self) | ||||
| { | ||||
|   long *buf; | ||||
|   int strut_size; | ||||
|  | ||||
|   strut_size = GTK_WIDGET (self)->allocation.height; | ||||
|  | ||||
|   buf = g_new0 (long, 4); | ||||
|   buf[0] = 0; /* left */ | ||||
|   buf[1] = 0; /* right */ | ||||
|   buf[2] = 0; /* top */ | ||||
|   buf[3] = strut_size; /* bottom */ | ||||
|   gdk_property_change (GTK_WIDGET (self)->window, gdk_atom_intern_static_string ("_NET_WM_STRUT"), | ||||
| 		       gdk_atom_intern_static_string ("CARDINAL"), 32, | ||||
| 		       GDK_PROP_MODE_REPLACE, | ||||
| 		       (guchar*) buf, 4); | ||||
|   g_free (buf); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_panel_window_size_request (GtkWidget *widget, GtkRequisition *requisition) | ||||
| { | ||||
|   ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget);   | ||||
|   GTK_WIDGET_CLASS (shell_panel_window_parent_class)->size_request(widget, requisition);   | ||||
|   requisition->width = self->priv->width; | ||||
|   requisition->height = PANEL_HEIGHT;  | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_panel_window_size_allocate (GtkWidget *widget, GtkAllocation *allocation) | ||||
| { | ||||
|   ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget); | ||||
|   GTK_WIDGET_CLASS (shell_panel_window_parent_class)->size_allocate(widget, allocation); | ||||
|   if (GTK_WIDGET_REALIZED (self)) | ||||
|     set_strut (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_panel_window_realize (GtkWidget *widget) | ||||
| { | ||||
|   ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget); | ||||
|   GTK_WIDGET_CLASS (shell_panel_window_parent_class)->realize(widget); | ||||
|   set_strut (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_panel_window_show (GtkWidget *widget) | ||||
| { | ||||
|   ShellPanelWindow *self = SHELL_PANEL_WINDOW (widget); | ||||
|   on_workarea_changed (self); | ||||
|   GTK_WIDGET_CLASS (shell_panel_window_parent_class)->show(widget); | ||||
| } | ||||
|  | ||||
| static void | ||||
| handle_new_workarea (ShellPanelWindow *self) | ||||
| { | ||||
|   GtkRequisition requisition; | ||||
|   int x, y; | ||||
|   int width; | ||||
|   int height; | ||||
|   int x_target, y_target; | ||||
|  | ||||
|   gtk_widget_size_request (GTK_WIDGET (self), &requisition); | ||||
|  | ||||
|   /* If we don't have a workarea, just use monitor */ | ||||
|   if (self->priv->workarea.width == 0)  | ||||
|     { | ||||
|       int monitor; | ||||
|       GdkRectangle monitor_geometry;       | ||||
|        | ||||
|       monitor = gdk_screen_get_monitor_at_point (gdk_screen_get_default (), | ||||
|                                                  0, 0); | ||||
|       gdk_screen_get_monitor_geometry (gdk_screen_get_default (), | ||||
|                                        monitor, &monitor_geometry);       | ||||
|       x = monitor_geometry.x; | ||||
|       y = monitor_geometry.y; | ||||
|       width = monitor_geometry.width; | ||||
|       height = monitor_geometry.height; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       x = self->priv->workarea.x; | ||||
|       y = self->priv->workarea.y; | ||||
|       width = self->priv->workarea.width; | ||||
|       height = self->priv->workarea.height; | ||||
|     } | ||||
|    | ||||
|   x_target = x; | ||||
|   y_target = y + height - requisition.height; | ||||
|  | ||||
|   self->priv->width = width; | ||||
|   self->priv->height = height; | ||||
|   gtk_widget_set_size_request (GTK_WIDGET (self), width - x_target, PANEL_HEIGHT); | ||||
|   gtk_window_move (GTK_WINDOW (self), x_target, y_target); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_workarea_changed (ShellPanelWindow *self) | ||||
| { | ||||
|   gulong bytes_after, nitems; | ||||
|   Atom type; | ||||
|   gint format; | ||||
|   guchar *data; | ||||
|   long *data32; | ||||
|   Atom workarea = gdk_x11_get_xatom_by_name_for_display (gdk_display_get_default (), "_NET_WORKAREA"); | ||||
|  | ||||
|   XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(), | ||||
| 		      workarea, | ||||
| 		      0, 4, FALSE, workarea, | ||||
| 		      &type, &format, &nitems, &bytes_after, &data); | ||||
|   if ((format == 32) && (nitems == 4) && (bytes_after == 0)) | ||||
|     { | ||||
|       int x, y, width, height; | ||||
|       data32 = (long*) data; | ||||
|       x = data32[0]; | ||||
|       y = data32[1]; | ||||
|       width = data32[2]; | ||||
|       height = data32[3]; | ||||
|       if (x == self->priv->workarea.x && y == self->priv->workarea.y  | ||||
|           && width == self->priv->workarea.width  | ||||
|           && height == self->priv->workarea.height) | ||||
|         return; | ||||
|  | ||||
|       self->priv->workarea.x = x; | ||||
|       self->priv->workarea.y = y; | ||||
|       self->priv->workarea.width = width; | ||||
|       self->priv->workarea.height = height; | ||||
|  | ||||
|       handle_new_workarea (self); | ||||
|     } | ||||
|   else if (nitems == 0) | ||||
|     { | ||||
|       /* We have no workarea set; assume there are no other panels at this time */ | ||||
|       self->priv->workarea.x = self->priv->workarea.y = 0; | ||||
|       self->priv->workarea.width = self->priv->workarea.height = 0; | ||||
|       handle_new_workarea (self); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       g_printerr ("unexpected return from XGetWindowProperty: %d %ld %ld\n", | ||||
|           format, nitems, bytes_after); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static GdkFilterReturn | ||||
| filter_func (GdkXEvent *gdk_xevent, | ||||
| 	     GdkEvent *event, | ||||
| 	     gpointer data) | ||||
| { | ||||
|   ShellPanelWindow *self = SHELL_PANEL_WINDOW (data); | ||||
|   GdkFilterReturn ret = GDK_FILTER_CONTINUE; | ||||
|   XEvent *xevent = (XEvent *) event; | ||||
|  | ||||
|   switch (xevent->type)  | ||||
|   { | ||||
|   case PropertyNotify: | ||||
|     { | ||||
|       if (xevent->xproperty.atom != self->priv->workarea_atom) | ||||
| 	break; | ||||
|       on_workarea_changed (self); | ||||
|     } | ||||
|     break; | ||||
|   default: | ||||
|     break; | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
| @@ -1,35 +0,0 @@ | ||||
| #ifndef __SHELL_PANEL_WINDOW_H__ | ||||
| #define __SHELL_PANEL_WINDOW_H__ | ||||
|  | ||||
| #include <gtk/gtk.h> | ||||
|  | ||||
| #define SHELL_TYPE_PANEL_WINDOW                 (shell_panel_window_get_type ()) | ||||
| #define SHELL_PANEL_WINDOW(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindow)) | ||||
| #define SHELL_PANEL_WINDOW_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindowClass)) | ||||
| #define SHELL_IS_PANEL_WINDOW(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_PANEL_WINDOW)) | ||||
| #define SHELL_IS_PANEL_WINDOW_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_PANEL_WINDOW)) | ||||
| #define SHELL_PANEL_WINDOW_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_PANEL_WINDOW, ShellPanelWindowClass)) | ||||
|  | ||||
| typedef struct _ShellPanelWindow ShellPanelWindow; | ||||
| typedef struct _ShellPanelWindowClass ShellPanelWindowClass; | ||||
|  | ||||
| typedef struct ShellPanelWindowPrivate ShellPanelWindowPrivate; | ||||
|  | ||||
| struct _ShellPanelWindow | ||||
| { | ||||
|     GtkWindow parent; | ||||
|  | ||||
|     ShellPanelWindowPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _ShellPanelWindowClass | ||||
| { | ||||
|     GtkWindowClass parent_class; | ||||
|  | ||||
| }; | ||||
|  | ||||
| GType shell_panel_window_get_type (void) G_GNUC_CONST; | ||||
| ShellPanelWindow* shell_panel_window_new(void); | ||||
|  | ||||
|  | ||||
| #endif /* __SHELL_PANEL_WINDOW_H__ */ | ||||
							
								
								
									
										777
									
								
								src/st/st-adjustment.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										777
									
								
								src/st/st-adjustment.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,777 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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 St by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:st-adjustment | ||||
|  * @short_description: A GObject representing an adjustable bounded value | ||||
|  * | ||||
|  * The #StAdjustment object represents a range of values bounded between a | ||||
|  * minimum and maximum, together with step and page increments and a page size. | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "st-adjustment.h" | ||||
| #include "st-marshal.h" | ||||
| #include "st-private.h" | ||||
|  | ||||
| G_DEFINE_TYPE (StAdjustment, st_adjustment, G_TYPE_OBJECT) | ||||
|  | ||||
| #define ADJUSTMENT_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_ADJUSTMENT, StAdjustmentPrivate)) | ||||
|  | ||||
| struct _StAdjustmentPrivate | ||||
| { | ||||
|   /* 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 st_adjustment_set_lower          (StAdjustment *adjustment, | ||||
|                                                   gdouble       lower); | ||||
| static gboolean st_adjustment_set_upper          (StAdjustment *adjustment, | ||||
|                                                   gdouble       upper); | ||||
| static gboolean st_adjustment_set_step_increment (StAdjustment *adjustment, | ||||
|                                                   gdouble       step); | ||||
| static gboolean st_adjustment_set_page_increment (StAdjustment *adjustment, | ||||
|                                                   gdouble       page); | ||||
| static gboolean st_adjustment_set_page_size      (StAdjustment *adjustment, | ||||
|                                                   gdouble       size); | ||||
|  | ||||
| static void | ||||
| st_adjustment_constructed (GObject *object) | ||||
| { | ||||
|   GObjectClass *g_class; | ||||
|   StAdjustment *self = ST_ADJUSTMENT (object); | ||||
|  | ||||
|   g_class = G_OBJECT_CLASS (st_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 != st_adjustment_constructed) | ||||
|     { | ||||
|       g_class->constructed (object); | ||||
|     } | ||||
|  | ||||
|   ST_ADJUSTMENT (self)->priv->is_constructing = FALSE; | ||||
|   st_adjustment_clamp_page (self, self->priv->lower, self->priv->upper); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_adjustment_get_property (GObject    *gobject, | ||||
|                             guint       prop_id, | ||||
|                             GValue     *value, | ||||
|                             GParamSpec *pspec) | ||||
| { | ||||
|   StAdjustmentPrivate *priv = ST_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 | ||||
| st_adjustment_set_property (GObject      *gobject, | ||||
|                             guint         prop_id, | ||||
|                             const GValue *value, | ||||
|                             GParamSpec   *pspec) | ||||
| { | ||||
|   StAdjustment *adj = ST_ADJUSTMENT (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_LOWER: | ||||
|       st_adjustment_set_lower (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_UPPER: | ||||
|       st_adjustment_set_upper (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_VALUE: | ||||
|       st_adjustment_set_value (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_STEP_INC: | ||||
|       st_adjustment_set_step_increment (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_PAGE_INC: | ||||
|       st_adjustment_set_page_increment (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_PAGE_SIZE: | ||||
|       st_adjustment_set_page_size (adj, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_ELASTIC: | ||||
|       st_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 (StAdjustment *adjustment) | ||||
| { | ||||
|   StAdjustmentPrivate *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 | ||||
| st_adjustment_dispose (GObject *object) | ||||
| { | ||||
|   stop_interpolation (ST_ADJUSTMENT (object)); | ||||
|  | ||||
|   G_OBJECT_CLASS (st_adjustment_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_adjustment_class_init (StAdjustmentClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (StAdjustmentPrivate)); | ||||
|  | ||||
|   object_class->constructed = st_adjustment_constructed; | ||||
|   object_class->get_property = st_adjustment_get_property; | ||||
|   object_class->set_property = st_adjustment_set_property; | ||||
|   object_class->dispose = st_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, | ||||
|                                                         ST_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, | ||||
|                                                         ST_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, | ||||
|                                                         ST_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, | ||||
|                                                         ST_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, | ||||
|                                                         ST_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, | ||||
|                                                         ST_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, | ||||
|                                                          ST_PARAM_READWRITE | | ||||
|                                                          G_PARAM_CONSTRUCT)); | ||||
|  | ||||
|   /** | ||||
|    * StAdjustment::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 (StAdjustmentClass, changed), | ||||
|                   NULL, NULL, | ||||
|                   _st_marshal_VOID__VOID, | ||||
|                   G_TYPE_NONE, 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_adjustment_init (StAdjustment *self) | ||||
| { | ||||
|   self->priv = ADJUSTMENT_PRIVATE (self); | ||||
|  | ||||
|   self->priv->is_constructing = TRUE; | ||||
| } | ||||
|  | ||||
| StAdjustment * | ||||
| st_adjustment_new (gdouble value, | ||||
|                    gdouble lower, | ||||
|                    gdouble upper, | ||||
|                    gdouble step_increment, | ||||
|                    gdouble page_increment, | ||||
|                    gdouble page_size) | ||||
| { | ||||
|   return g_object_new (ST_TYPE_ADJUSTMENT, | ||||
|                        "value", value, | ||||
|                        "lower", lower, | ||||
|                        "upper", upper, | ||||
|                        "step-increment", step_increment, | ||||
|                        "page-increment", page_increment, | ||||
|                        "page-size", page_size, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| gdouble | ||||
| st_adjustment_get_value (StAdjustment *adjustment) | ||||
| { | ||||
|   StAdjustmentPrivate *priv; | ||||
|  | ||||
|   g_return_val_if_fail (ST_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 | ||||
| st_adjustment_set_value (StAdjustment *adjustment, | ||||
|                          gdouble       value) | ||||
| { | ||||
|   StAdjustmentPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_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 | ||||
| st_adjustment_clamp_page (StAdjustment *adjustment, | ||||
|                           gdouble       lower, | ||||
|                           gdouble       upper) | ||||
| { | ||||
|   StAdjustmentPrivate *priv; | ||||
|   gboolean changed; | ||||
|  | ||||
|   g_return_if_fail (ST_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 | ||||
| st_adjustment_set_lower (StAdjustment *adjustment, | ||||
|                          gdouble       lower) | ||||
| { | ||||
|   StAdjustmentPrivate *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) | ||||
|         st_adjustment_clamp_page (adjustment, priv->lower, priv->upper); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| st_adjustment_set_upper (StAdjustment *adjustment, | ||||
|                          gdouble       upper) | ||||
| { | ||||
|   StAdjustmentPrivate *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) | ||||
|         st_adjustment_clamp_page (adjustment, priv->lower, priv->upper); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| st_adjustment_set_step_increment (StAdjustment *adjustment, | ||||
|                                   gdouble       step) | ||||
| { | ||||
|   StAdjustmentPrivate *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 | ||||
| st_adjustment_set_page_increment (StAdjustment *adjustment, | ||||
|                                   gdouble       page) | ||||
| { | ||||
|   StAdjustmentPrivate *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 | ||||
| st_adjustment_set_page_size (StAdjustment *adjustment, | ||||
|                              gdouble       size) | ||||
| { | ||||
|   StAdjustmentPrivate *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) | ||||
|         st_adjustment_clamp_page (adjustment, priv->lower, priv->upper); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| void | ||||
| st_adjustment_set_values (StAdjustment *adjustment, | ||||
|                           gdouble       value, | ||||
|                           gdouble       lower, | ||||
|                           gdouble       upper, | ||||
|                           gdouble       step_increment, | ||||
|                           gdouble       page_increment, | ||||
|                           gdouble       page_size) | ||||
| { | ||||
|   StAdjustmentPrivate *priv; | ||||
|   gboolean emit_changed = FALSE; | ||||
|  | ||||
|   g_return_if_fail (ST_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 |= st_adjustment_set_lower (adjustment, lower); | ||||
|   emit_changed |= st_adjustment_set_upper (adjustment, upper); | ||||
|   emit_changed |= st_adjustment_set_step_increment (adjustment, step_increment); | ||||
|   emit_changed |= st_adjustment_set_page_increment (adjustment, page_increment); | ||||
|   emit_changed |= st_adjustment_set_page_size (adjustment, page_size); | ||||
|  | ||||
|   if (value != priv->value) | ||||
|     { | ||||
|       st_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 | ||||
| st_adjustment_get_values (StAdjustment *adjustment, | ||||
|                           gdouble      *value, | ||||
|                           gdouble      *lower, | ||||
|                           gdouble      *upper, | ||||
|                           gdouble      *step_increment, | ||||
|                           gdouble      *page_increment, | ||||
|                           gdouble      *page_size) | ||||
| { | ||||
|   StAdjustmentPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_ADJUSTMENT (adjustment)); | ||||
|  | ||||
|   priv = adjustment->priv; | ||||
|  | ||||
|   if (lower) | ||||
|     *lower = priv->lower; | ||||
|  | ||||
|   if (upper) | ||||
|     *upper = priv->upper; | ||||
|  | ||||
|   if (value) | ||||
|     *value = st_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, | ||||
|                             StAdjustment    *adjustment) | ||||
| { | ||||
|   StAdjustmentPrivate *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; | ||||
|  | ||||
|       st_adjustment_set_value (adjustment, dx); | ||||
|     } | ||||
|   else | ||||
|     st_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, | ||||
|                             StAdjustment    *adjustment) | ||||
| { | ||||
|   StAdjustmentPrivate *priv = adjustment->priv; | ||||
|  | ||||
|   stop_interpolation (adjustment); | ||||
|   st_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 | ||||
| st_adjustment_interpolate (StAdjustment *adjustment, | ||||
|                            gdouble       value, | ||||
|                            guint         duration) | ||||
| { | ||||
|   StAdjustmentPrivate *priv = adjustment->priv; | ||||
|  | ||||
|   stop_interpolation (adjustment); | ||||
|  | ||||
|   if (duration <= 1) | ||||
|     { | ||||
|       st_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 | ||||
| st_adjustment_get_elastic (StAdjustment *adjustment) | ||||
| { | ||||
|   return adjustment->priv->elastic; | ||||
| } | ||||
|  | ||||
| void | ||||
| st_adjustment_set_elastic (StAdjustment *adjustment, | ||||
|                            gboolean      elastic) | ||||
| { | ||||
|   adjustment->priv->elastic = elastic; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| st_adjustment_clamp (StAdjustment *adjustment, | ||||
|                      gboolean      interpolate, | ||||
|                      guint         duration) | ||||
| { | ||||
|   StAdjustmentPrivate *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) | ||||
|         st_adjustment_interpolate (adjustment, dest, duration); | ||||
|       else | ||||
|         st_adjustment_set_value (adjustment, dest); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
							
								
								
									
										122
									
								
								src/st/st-adjustment.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								src/st/st-adjustment.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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 St by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_ADJUSTMENT_H__ | ||||
| #define __ST_ADJUSTMENT_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_ADJUSTMENT            (st_adjustment_get_type()) | ||||
| #define ST_ADJUSTMENT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_ADJUSTMENT, StAdjustment)) | ||||
| #define ST_IS_ADJUSTMENT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_ADJUSTMENT)) | ||||
| #define ST_ADJUSTMENT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_ADJUSTMENT, StAdjustmentClass)) | ||||
| #define ST_IS_ADJUSTMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_ADJUSTMENT)) | ||||
| #define ST_ADJUSTMENT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_ADJUSTMENT, StAdjustmentClass)) | ||||
|  | ||||
| typedef struct _StAdjustment          StAdjustment; | ||||
| typedef struct _StAdjustmentPrivate   StAdjustmentPrivate; | ||||
| typedef struct _StAdjustmentClass     StAdjustmentClass; | ||||
|  | ||||
| /** | ||||
|  * StAdjustment: | ||||
|  * | ||||
|  * Class for handling an interval between to values. The contents of | ||||
|  * the #StAdjustment are private and should be accessed using the | ||||
|  * public API. | ||||
|  */ | ||||
| struct _StAdjustment | ||||
| { | ||||
|   /*< private >*/ | ||||
|   GObject parent_instance; | ||||
|  | ||||
|   StAdjustmentPrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * StAdjustmentClass | ||||
|  * @changed: Class handler for the ::changed signal. | ||||
|  * | ||||
|  * Base class for #StAdjustment. | ||||
|  */ | ||||
| struct _StAdjustmentClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   /*< public >*/ | ||||
|   void (* changed) (StAdjustment *adjustment); | ||||
| }; | ||||
|  | ||||
| GType st_adjustment_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| StAdjustment *st_adjustment_new         (gdouble       value, | ||||
|                                          gdouble       lower, | ||||
|                                          gdouble       upper, | ||||
|                                          gdouble       step_increment, | ||||
|                                          gdouble       page_increment, | ||||
|                                          gdouble       page_size); | ||||
| gdouble       st_adjustment_get_value   (StAdjustment *adjustment); | ||||
| void          st_adjustment_set_value   (StAdjustment *adjustment, | ||||
|                                          gdouble       value); | ||||
| void          st_adjustment_clamp_page  (StAdjustment *adjustment, | ||||
|                                          gdouble       lower, | ||||
|                                          gdouble       upper); | ||||
| void          st_adjustment_set_values  (StAdjustment *adjustment, | ||||
|                                          gdouble       value, | ||||
|                                          gdouble       lower, | ||||
|                                          gdouble       upper, | ||||
|                                          gdouble       step_increment, | ||||
|                                          gdouble       page_increment, | ||||
|                                          gdouble       page_size); | ||||
| void          st_adjustment_get_values  (StAdjustment *adjustment, | ||||
|                                          gdouble      *value, | ||||
|                                          gdouble      *lower, | ||||
|                                          gdouble      *upper, | ||||
|                                          gdouble      *step_increment, | ||||
|                                          gdouble      *page_increment, | ||||
|                                          gdouble      *page_size); | ||||
|  | ||||
| void          st_adjustment_interpolate (StAdjustment *adjustment, | ||||
|                                          gdouble       value, | ||||
|                                          guint         duration); | ||||
|  | ||||
| gboolean      st_adjustment_get_elastic (StAdjustment *adjustment); | ||||
| void          st_adjustment_set_elastic (StAdjustment *adjustment, | ||||
|                                          gboolean      elastic); | ||||
|  | ||||
| gboolean      st_adjustment_clamp       (StAdjustment *adjustment, | ||||
|                                          gboolean      interpolate, | ||||
|                                          guint         duration); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_ADJUSTMENT_H__ */ | ||||
							
								
								
									
										748
									
								
								src/st/st-bin.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										748
									
								
								src/st/st-bin.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,748 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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:st-bin | ||||
|  * @short_description: a simple container with one actor | ||||
|  * | ||||
|  * #StBin is a simple container capable of having only one | ||||
|  * #ClutterActor as a child. | ||||
|  * | ||||
|  * #StBin inherits from #StWidget, so it is fully themable. | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "st-bin.h" | ||||
| #include "st-enum-types.h" | ||||
| #include "st-private.h" | ||||
|  | ||||
| #define ST_BIN_GET_PRIVATE(obj)       (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_BIN, StBinPrivate)) | ||||
|  | ||||
| struct _StBinPrivate | ||||
| { | ||||
|   ClutterActor *child; | ||||
|  | ||||
|   StAlign       x_align; | ||||
|   StAlign       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 (StBin, st_bin, ST_TYPE_WIDGET, | ||||
|                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, | ||||
|                                                 clutter_container_iface_init)); | ||||
|  | ||||
| void | ||||
| _st_bin_get_align_factors (StBin   *bin, | ||||
|                            gdouble *x_align, | ||||
|                            gdouble *y_align) | ||||
| { | ||||
|   StBinPrivate *priv = bin->priv; | ||||
|   gdouble factor; | ||||
|  | ||||
|   switch (priv->x_align) | ||||
|     { | ||||
|     case ST_ALIGN_START: | ||||
|       factor = 0.0; | ||||
|       break; | ||||
|  | ||||
|     case ST_ALIGN_MIDDLE: | ||||
|       factor = 0.5; | ||||
|       break; | ||||
|  | ||||
|     case ST_ALIGN_END: | ||||
|       factor = 1.0; | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       factor = 0.0; | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   if (x_align) | ||||
|     *x_align = factor; | ||||
|  | ||||
|   switch (priv->y_align) | ||||
|     { | ||||
|     case ST_ALIGN_START: | ||||
|       factor = 0.0; | ||||
|       break; | ||||
|  | ||||
|     case ST_ALIGN_MIDDLE: | ||||
|       factor = 0.5; | ||||
|       break; | ||||
|  | ||||
|     case ST_ALIGN_END: | ||||
|       factor = 1.0; | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       factor = 0.0; | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   if (y_align) | ||||
|     *y_align = factor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_bin_add (ClutterContainer *container, | ||||
|             ClutterActor     *actor) | ||||
| { | ||||
|   st_bin_set_child (ST_BIN (container), actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_bin_remove (ClutterContainer *container, | ||||
|                ClutterActor     *actor) | ||||
| { | ||||
|   StBinPrivate *priv = ST_BIN (container)->priv; | ||||
|  | ||||
|   if (priv->child == actor) | ||||
|     st_bin_set_child (ST_BIN (container), NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_bin_foreach (ClutterContainer *container, | ||||
|                 ClutterCallback   callback, | ||||
|                 gpointer          user_data) | ||||
| { | ||||
|   StBinPrivate *priv = ST_BIN (container)->priv; | ||||
|  | ||||
|   if (priv->child) | ||||
|     callback (priv->child, user_data); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_container_iface_init (ClutterContainerIface *iface) | ||||
| { | ||||
|   iface->add = st_bin_add; | ||||
|   iface->remove = st_bin_remove; | ||||
|   iface->foreach = st_bin_foreach; | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_bin_paint (ClutterActor *self) | ||||
| { | ||||
|   StBinPrivate *priv = ST_BIN (self)->priv; | ||||
|  | ||||
|   /* allow StWidget to paint the background */ | ||||
|   CLUTTER_ACTOR_CLASS (st_bin_parent_class)->paint (self); | ||||
|  | ||||
|   /* the pain our child */ | ||||
|   if (priv->child) | ||||
|     clutter_actor_paint (priv->child); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_bin_pick (ClutterActor       *self, | ||||
|              const ClutterColor *pick_color) | ||||
| { | ||||
|   StBinPrivate *priv = ST_BIN (self)->priv; | ||||
|  | ||||
|   /* get the default pick implementation */ | ||||
|   CLUTTER_ACTOR_CLASS (st_bin_parent_class)->pick (self, pick_color); | ||||
|  | ||||
|   if (priv->child) | ||||
|     clutter_actor_paint (priv->child); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_bin_allocate (ClutterActor          *self, | ||||
|                  const ClutterActorBox *box, | ||||
|                  ClutterAllocationFlags flags) | ||||
| { | ||||
|   StBinPrivate *priv = ST_BIN (self)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (st_bin_parent_class)->allocate (self, box, | ||||
|                                                        flags); | ||||
|  | ||||
|   if (priv->child) | ||||
|     { | ||||
|       StThemeNode *theme_node = st_widget_get_theme_node (ST_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; | ||||
|  | ||||
|       st_theme_node_get_content_box (theme_node, box, &content_box); | ||||
|  | ||||
|       _st_bin_get_align_factors (ST_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 | ||||
| st_bin_get_preferred_width (ClutterActor *self, | ||||
|                             gfloat        for_height, | ||||
|                             gfloat       *min_width_p, | ||||
|                             gfloat       *natural_width_p) | ||||
| { | ||||
|   StBinPrivate *priv = ST_BIN (self)->priv; | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self)); | ||||
|  | ||||
|   st_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); | ||||
|     } | ||||
|  | ||||
|   st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_bin_get_preferred_height (ClutterActor *self, | ||||
|                              gfloat        for_width, | ||||
|                              gfloat       *min_height_p, | ||||
|                              gfloat       *natural_height_p) | ||||
| { | ||||
|   StBinPrivate *priv = ST_BIN (self)->priv; | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self)); | ||||
|  | ||||
|   st_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); | ||||
|     } | ||||
|  | ||||
|   st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_bin_dispose (GObject *gobject) | ||||
| { | ||||
|   StBinPrivate *priv = ST_BIN (gobject)->priv; | ||||
|  | ||||
|   if (priv->child) | ||||
|     { | ||||
|       clutter_actor_unparent (priv->child); | ||||
|       priv->child = NULL; | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (st_bin_parent_class)->dispose (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_bin_set_property (GObject      *gobject, | ||||
|                      guint         prop_id, | ||||
|                      const GValue *value, | ||||
|                      GParamSpec   *pspec) | ||||
| { | ||||
|   StBin *bin = ST_BIN (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_CHILD: | ||||
|       st_bin_set_child (bin, g_value_get_object (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_X_ALIGN: | ||||
|       st_bin_set_alignment (bin, | ||||
|                             g_value_get_enum (value), | ||||
|                             bin->priv->y_align); | ||||
|       break; | ||||
|  | ||||
|     case PROP_Y_ALIGN: | ||||
|       st_bin_set_alignment (bin, | ||||
|                             bin->priv->x_align, | ||||
|                             g_value_get_enum (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_X_FILL: | ||||
|       st_bin_set_fill (bin, | ||||
|                        g_value_get_boolean (value), | ||||
|                        bin->priv->y_fill); | ||||
|       break; | ||||
|  | ||||
|     case PROP_Y_FILL: | ||||
|       st_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 | ||||
| st_bin_get_property (GObject    *gobject, | ||||
|                      guint       prop_id, | ||||
|                      GValue     *value, | ||||
|                      GParamSpec *pspec) | ||||
| { | ||||
|   StBinPrivate *priv = ST_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; | ||||
|  | ||||
|     case PROP_X_ALIGN: | ||||
|       g_value_set_enum (value, priv->x_align); | ||||
|       break; | ||||
|  | ||||
|     case PROP_Y_ALIGN: | ||||
|       g_value_set_enum (value, priv->y_align); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_bin_class_init (StBinClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (StBinPrivate)); | ||||
|  | ||||
|   gobject_class->set_property = st_bin_set_property; | ||||
|   gobject_class->get_property = st_bin_get_property; | ||||
|   gobject_class->dispose = st_bin_dispose; | ||||
|  | ||||
|   actor_class->get_preferred_width = st_bin_get_preferred_width; | ||||
|   actor_class->get_preferred_height = st_bin_get_preferred_height; | ||||
|   actor_class->allocate = st_bin_allocate; | ||||
|   actor_class->paint = st_bin_paint; | ||||
|   actor_class->pick = st_bin_pick; | ||||
|  | ||||
|   /** | ||||
|    * StBin:child: | ||||
|    * | ||||
|    * The child #ClutterActor of the #StBin container. | ||||
|    */ | ||||
|   pspec = g_param_spec_object ("child", | ||||
|                                "Child", | ||||
|                                "The child of the Bin", | ||||
|                                CLUTTER_TYPE_ACTOR, | ||||
|                                ST_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_CHILD, pspec); | ||||
|  | ||||
|   /** | ||||
|    * StBin:x-align: | ||||
|    * | ||||
|    * The horizontal alignment of the #StBin child. | ||||
|    */ | ||||
|   pspec = g_param_spec_enum ("x-align", | ||||
|                              "X Align", | ||||
|                              "The horizontal alignment", | ||||
|                              ST_TYPE_ALIGN, | ||||
|                              ST_ALIGN_MIDDLE, | ||||
|                              ST_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_X_ALIGN, pspec); | ||||
|  | ||||
|   /** | ||||
|    * StBin:y-align: | ||||
|    * | ||||
|    * The vertical alignment of the #StBin child. | ||||
|    */ | ||||
|   pspec = g_param_spec_enum ("y-align", | ||||
|                              "Y Align", | ||||
|                              "The vertical alignment", | ||||
|                              ST_TYPE_ALIGN, | ||||
|                              ST_ALIGN_MIDDLE, | ||||
|                              ST_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_Y_ALIGN, pspec); | ||||
|  | ||||
|   /** | ||||
|    * StBin: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, | ||||
|                                 ST_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_X_FILL, pspec); | ||||
|  | ||||
|   /** | ||||
|    * StBin: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, | ||||
|                                 ST_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_Y_FILL, pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_bin_init (StBin *bin) | ||||
| { | ||||
|   bin->priv = ST_BIN_GET_PRIVATE (bin); | ||||
|  | ||||
|   bin->priv->x_align = ST_ALIGN_MIDDLE; | ||||
|   bin->priv->y_align = ST_ALIGN_MIDDLE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_bin_new: | ||||
|  * | ||||
|  * Creates a new #StBin, a simple container for one child. | ||||
|  * | ||||
|  * Return value: the newly created #StBin actor | ||||
|  */ | ||||
| StWidget * | ||||
| st_bin_new (void) | ||||
| { | ||||
|   return g_object_new (ST_TYPE_BIN, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_bin_set_child: | ||||
|  * @bin: a #StBin | ||||
|  * @child: a #ClutterActor, or %NULL | ||||
|  * | ||||
|  * Sets @child as the child of @bin. | ||||
|  * | ||||
|  * If @bin already has a child, the previous child is removed. | ||||
|  */ | ||||
| void | ||||
| st_bin_set_child (StBin        *bin, | ||||
|                   ClutterActor *child) | ||||
| { | ||||
|   StBinPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_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"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_bin_get_child: | ||||
|  * @bin: a #StBin | ||||
|  * | ||||
|  * Retrieves a pointer to the child of @bin. | ||||
|  * | ||||
|  * Return value: (transfer none): a #ClutterActor, or %NULL | ||||
|  */ | ||||
| ClutterActor * | ||||
| st_bin_get_child (StBin *bin) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_BIN (bin), NULL); | ||||
|  | ||||
|   return bin->priv->child; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_bin_set_alignment: | ||||
|  * @bin: a #StBin | ||||
|  * @x_align: horizontal alignment | ||||
|  * @y_align: vertical alignment | ||||
|  * | ||||
|  * Sets the horizontal and vertical alignment of the child | ||||
|  * inside a #StBin. | ||||
|  */ | ||||
| void | ||||
| st_bin_set_alignment (StBin  *bin, | ||||
|                       StAlign x_align, | ||||
|                       StAlign y_align) | ||||
| { | ||||
|   StBinPrivate *priv; | ||||
|   gboolean changed = FALSE; | ||||
|  | ||||
|   g_return_if_fail (ST_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)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_bin_get_alignment: | ||||
|  * @bin: a #StBin | ||||
|  * @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 #StBin, as set by st_bin_set_alignment(). | ||||
|  */ | ||||
| void | ||||
| st_bin_get_alignment (StBin   *bin, | ||||
|                       StAlign *x_align, | ||||
|                       StAlign *y_align) | ||||
| { | ||||
|   StBinPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_BIN (bin)); | ||||
|  | ||||
|   priv = bin->priv; | ||||
|  | ||||
|   if (x_align) | ||||
|     *x_align = priv->x_align; | ||||
|  | ||||
|   if (y_align) | ||||
|     *y_align = priv->y_align; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_bin_set_fill: | ||||
|  * @bin: a #StBin | ||||
|  * @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 | ||||
| st_bin_set_fill (StBin   *bin, | ||||
|                  gboolean x_fill, | ||||
|                  gboolean y_fill) | ||||
| { | ||||
|   StBinPrivate *priv; | ||||
|   gboolean changed = FALSE; | ||||
|  | ||||
|   g_return_if_fail (ST_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)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_bin_get_fill: | ||||
|  * @bin: a #StBin | ||||
|  * @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 | ||||
| st_bin_get_fill (StBin    *bin, | ||||
|                  gboolean *x_fill, | ||||
|                  gboolean *y_fill) | ||||
| { | ||||
|   g_return_if_fail (ST_IS_BIN (bin)); | ||||
|  | ||||
|   if (x_fill) | ||||
|     *x_fill = bin->priv->x_fill; | ||||
|  | ||||
|   if (y_fill) | ||||
|     *y_fill = bin->priv->y_fill; | ||||
| } | ||||
							
								
								
									
										93
									
								
								src/st/st-bin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/st/st-bin.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_BIN_H__ | ||||
| #define __ST_BIN_H__ | ||||
|  | ||||
| #include <st/st-types.h> | ||||
| #include <st/st-widget.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_BIN                   (st_bin_get_type ()) | ||||
| #define ST_BIN(obj)                   (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_BIN, StBin)) | ||||
| #define ST_IS_BIN(obj)                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_BIN)) | ||||
| #define ST_BIN_CLASS(klass)           (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_BIN, StBinClass)) | ||||
| #define ST_IS_BIN_CLASS(klass)        (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_BIN)) | ||||
| #define ST_BIN_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_BIN, StBinClass)) | ||||
|  | ||||
| typedef struct _StBin                 StBin; | ||||
| typedef struct _StBinPrivate          StBinPrivate; | ||||
| typedef struct _StBinClass            StBinClass; | ||||
|  | ||||
| /** | ||||
|  * StBin: | ||||
|  * | ||||
|  * The #StBin struct contains only private data | ||||
|  */ | ||||
| struct _StBin | ||||
| { | ||||
|   /*< private >*/ | ||||
|   StWidget parent_instance; | ||||
|  | ||||
|   StBinPrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * StBinClass: | ||||
|  * | ||||
|  * The #StBinClass struct contains only private data | ||||
|  */ | ||||
| struct _StBinClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   StWidgetClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType st_bin_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| StWidget   *  st_bin_new           (void); | ||||
| void          st_bin_set_child     (StBin        *bin, | ||||
|                                     ClutterActor *child); | ||||
| ClutterActor *st_bin_get_child     (StBin        *bin); | ||||
| void          st_bin_set_alignment (StBin        *bin, | ||||
|                                     StAlign       x_align, | ||||
|                                     StAlign       y_align); | ||||
| void          st_bin_get_alignment (StBin        *bin, | ||||
|                                     StAlign      *x_align, | ||||
|                                     StAlign      *y_align); | ||||
| void          st_bin_set_fill      (StBin        *bin, | ||||
|                                     gboolean      x_fill, | ||||
|                                     gboolean      y_fill); | ||||
| void          st_bin_get_fill      (StBin        *bin, | ||||
|                                     gboolean     *x_fill, | ||||
|                                     gboolean     *y_fill); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_BIN_H__ */ | ||||
							
								
								
									
										92
									
								
								src/st/st-border-image.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/st/st-border-image.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include "st-border-image.h" | ||||
|  | ||||
| struct _StBorderImage { | ||||
|   GObject parent; | ||||
|  | ||||
|   char *filename; | ||||
|   int border_top; | ||||
|   int border_right; | ||||
|   int border_bottom; | ||||
|   int border_left; | ||||
| }; | ||||
|  | ||||
| struct _StBorderImageClass { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (StBorderImage, st_border_image, G_TYPE_OBJECT) | ||||
|  | ||||
| static void | ||||
| st_border_image_finalize (GObject *object) | ||||
| { | ||||
|   StBorderImage *image = ST_BORDER_IMAGE (object); | ||||
|  | ||||
|   g_free (image->filename); | ||||
|  | ||||
|   G_OBJECT_CLASS (st_border_image_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_border_image_class_init (StBorderImageClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = st_border_image_finalize; | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_border_image_init (StBorderImage *image) | ||||
| { | ||||
| } | ||||
|  | ||||
| StBorderImage * | ||||
| st_border_image_new (const char *filename, | ||||
|                        int         border_top, | ||||
|                        int         border_right, | ||||
|                        int         border_bottom, | ||||
|                        int         border_left) | ||||
| { | ||||
|   StBorderImage *image; | ||||
|  | ||||
|   image = g_object_new (ST_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 * | ||||
| st_border_image_get_filename (StBorderImage *image) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_BORDER_IMAGE (image), NULL); | ||||
|  | ||||
|   return image->filename; | ||||
| } | ||||
|  | ||||
| void | ||||
| st_border_image_get_borders (StBorderImage *image, | ||||
|                              int           *border_top, | ||||
|                              int           *border_right, | ||||
|                              int           *border_bottom, | ||||
|                              int           *border_left) | ||||
| { | ||||
|   g_return_if_fail (ST_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/st/st-border-image.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/st/st-border-image.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| #ifndef __ST_BORDER_IMAGE_H__ | ||||
| #define __ST_BORDER_IMAGE_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| /* A StBorderImage encapsulates an image with specified unscaled borders on each edge. | ||||
|  */ | ||||
| typedef struct _StBorderImage      StBorderImage; | ||||
| typedef struct _StBorderImageClass StBorderImageClass; | ||||
|  | ||||
| #define ST_TYPE_BORDER_IMAGE             (st_border_image_get_type ()) | ||||
| #define ST_BORDER_IMAGE(object)          (G_TYPE_CHECK_INSTANCE_CAST ((object), ST_TYPE_BORDER_IMAGE, StBorderImage)) | ||||
| #define ST_BORDER_IMAGE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_BORDER_IMAGE, StBorderImageClass)) | ||||
| #define ST_IS_BORDER_IMAGE(object)       (G_TYPE_CHECK_INSTANCE_TYPE ((object), ST_TYPE_BORDER_IMAGE)) | ||||
| #define ST_IS_BORDER_IMAGE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_BORDER_IMAGE)) | ||||
| #define ST_BORDER_IMAGE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_BORDER_IMAGE, StBorderImageClass)) | ||||
|  | ||||
| GType             st_border_image_get_type          (void) G_GNUC_CONST; | ||||
|  | ||||
| StBorderImage *st_border_image_new (const char *filename, | ||||
|                                     int         border_top, | ||||
|                                     int         border_right, | ||||
|                                     int         border_bottom, | ||||
|                                     int         border_left); | ||||
|  | ||||
| const char *st_border_image_get_filename (StBorderImage *image); | ||||
| void        st_border_image_get_borders  (StBorderImage *image, | ||||
|                                           int           *border_top, | ||||
|                                           int           *border_right, | ||||
|                                           int           *border_bottom, | ||||
|                                           int           *border_left); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_BORDER_IMAGE_H__ */ | ||||
							
								
								
									
										190
									
								
								src/st/st-box-layout-child.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								src/st/st-box-layout-child.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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> | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:st-box-layout-child | ||||
|  * @short_description: meta data associated with a #StBoxLayout child. | ||||
|  * | ||||
|  * #StBoxLayoutChild is a #ClutterChildMeta implementation that stores the | ||||
|  * child properties for children inside a #StBoxLayout. | ||||
|  */ | ||||
|  | ||||
| #include "st-box-layout-child.h" | ||||
| #include "st-private.h" | ||||
|  | ||||
| G_DEFINE_TYPE (StBoxLayoutChild, st_box_layout_child, CLUTTER_TYPE_CHILD_META) | ||||
|  | ||||
| #define BOX_LAYOUT_CHILD_PRIVATE(o) \ | ||||
|   (G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_BOX_LAYOUT_CHILD, StBoxLayoutChildPrivate)) | ||||
|  | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_EXPAND, | ||||
|   PROP_X_FILL, | ||||
|   PROP_Y_FILL, | ||||
|   PROP_X_ALIGN, | ||||
|   PROP_Y_ALIGN | ||||
| }; | ||||
|  | ||||
| static void | ||||
| st_box_layout_child_get_property (GObject    *object, | ||||
|                                   guint       property_id, | ||||
|                                   GValue     *value, | ||||
|                                   GParamSpec *pspec) | ||||
| { | ||||
|   StBoxLayoutChild *child = ST_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 | ||||
| st_box_layout_child_set_property (GObject      *object, | ||||
|                                   guint         property_id, | ||||
|                                   const GValue *value, | ||||
|                                   GParamSpec   *pspec) | ||||
| { | ||||
|   StBoxLayoutChild *child = ST_BOX_LAYOUT_CHILD (object); | ||||
|   StBoxLayout *box = ST_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 | ||||
| st_box_layout_child_dispose (GObject *object) | ||||
| { | ||||
|   G_OBJECT_CLASS (st_box_layout_child_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_box_layout_child_finalize (GObject *object) | ||||
| { | ||||
|   G_OBJECT_CLASS (st_box_layout_child_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_box_layout_child_class_init (StBoxLayoutChildClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   object_class->get_property = st_box_layout_child_get_property; | ||||
|   object_class->set_property = st_box_layout_child_set_property; | ||||
|   object_class->dispose = st_box_layout_child_dispose; | ||||
|   object_class->finalize = st_box_layout_child_finalize; | ||||
|  | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("expand", "Expand", | ||||
|                                 "Allocate the child extra space", | ||||
|                                 FALSE, | ||||
|                                 ST_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, | ||||
|                                 ST_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, | ||||
|                                 ST_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", | ||||
|                              ST_TYPE_ALIGN, | ||||
|                              ST_ALIGN_MIDDLE, | ||||
|                              ST_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", | ||||
|                              ST_TYPE_ALIGN, | ||||
|                              ST_ALIGN_MIDDLE, | ||||
|                              ST_PARAM_READWRITE); | ||||
|   g_object_class_install_property (object_class, PROP_Y_ALIGN, pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_box_layout_child_init (StBoxLayoutChild *self) | ||||
| { | ||||
|   self->expand = FALSE; | ||||
|  | ||||
|   self->x_fill = TRUE; | ||||
|   self->y_fill = TRUE; | ||||
|  | ||||
|   self->x_align = ST_ALIGN_MIDDLE; | ||||
|   self->y_align = ST_ALIGN_MIDDLE; | ||||
| } | ||||
|  | ||||
							
								
								
									
										85
									
								
								src/st/st-box-layout-child.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/st/st-box-layout-child.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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 _ST_BOX_LAYOUT_CHILD_H | ||||
| #define _ST_BOX_LAYOUT_CHILD_H | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include "st-enum-types.h" | ||||
| #include "st-box-layout.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_BOX_LAYOUT_CHILD st_box_layout_child_get_type() | ||||
|  | ||||
| #define ST_BOX_LAYOUT_CHILD(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ | ||||
|   ST_TYPE_BOX_LAYOUT_CHILD, StBoxLayoutChild)) | ||||
|  | ||||
| #define ST_BOX_LAYOUT_CHILD_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_CAST ((klass), \ | ||||
|   ST_TYPE_BOX_LAYOUT_CHILD, StBoxLayoutChildClass)) | ||||
|  | ||||
| #define ST_IS_BOX_LAYOUT_CHILD(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ | ||||
|   ST_TYPE_BOX_LAYOUT_CHILD)) | ||||
|  | ||||
| #define ST_IS_BOX_LAYOUT_CHILD_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_TYPE ((klass), \ | ||||
|   ST_TYPE_BOX_LAYOUT_CHILD)) | ||||
|  | ||||
| #define ST_BOX_LAYOUT_CHILD_GET_CLASS(obj) \ | ||||
|   (G_TYPE_INSTANCE_GET_CLASS ((obj), \ | ||||
|   ST_TYPE_BOX_LAYOUT_CHILD, StBoxLayoutChildClass)) | ||||
|  | ||||
| typedef struct _StBoxLayoutChild StBoxLayoutChild; | ||||
| typedef struct _StBoxLayoutChildClass StBoxLayoutChildClass; | ||||
| typedef struct _StBoxLayoutChildPrivate StBoxLayoutChildPrivate; | ||||
|  | ||||
| /** | ||||
|  * StBoxLayoutChild: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _StBoxLayoutChild | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterChildMeta parent; | ||||
|  | ||||
|   gboolean expand; | ||||
|   gboolean x_fill : 1; | ||||
|   gboolean y_fill : 1; | ||||
|   StAlign x_align; | ||||
|   StAlign y_align; | ||||
| }; | ||||
|  | ||||
| struct _StBoxLayoutChildClass | ||||
| { | ||||
|   ClutterChildMetaClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType st_box_layout_child_get_type (void); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* _ST_BOX_LAYOUT_CHILD_H */ | ||||
							
								
								
									
										1227
									
								
								src/st/st-box-layout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1227
									
								
								src/st/st-box-layout.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										94
									
								
								src/st/st-box-layout.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/st/st-box-layout.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef _ST_BOX_LAYOUT_H | ||||
| #define _ST_BOX_LAYOUT_H | ||||
|  | ||||
| #include <st/st-widget.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_BOX_LAYOUT st_box_layout_get_type() | ||||
|  | ||||
| #define ST_BOX_LAYOUT(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ | ||||
|   ST_TYPE_BOX_LAYOUT, StBoxLayout)) | ||||
|  | ||||
| #define ST_BOX_LAYOUT_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_CAST ((klass), \ | ||||
|   ST_TYPE_BOX_LAYOUT, StBoxLayoutClass)) | ||||
|  | ||||
| #define ST_IS_BOX_LAYOUT(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ | ||||
|   ST_TYPE_BOX_LAYOUT)) | ||||
|  | ||||
| #define ST_IS_BOX_LAYOUT_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_TYPE ((klass), \ | ||||
|   ST_TYPE_BOX_LAYOUT)) | ||||
|  | ||||
| #define ST_BOX_LAYOUT_GET_CLASS(obj) \ | ||||
|   (G_TYPE_INSTANCE_GET_CLASS ((obj), \ | ||||
|   ST_TYPE_BOX_LAYOUT, StBoxLayoutClass)) | ||||
|  | ||||
| typedef struct _StBoxLayout StBoxLayout; | ||||
| typedef struct _StBoxLayoutClass StBoxLayoutClass; | ||||
| typedef struct _StBoxLayoutPrivate StBoxLayoutPrivate; | ||||
|  | ||||
| /** | ||||
|  * StBoxLayout: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _StBoxLayout | ||||
| { | ||||
|   /*< private >*/ | ||||
|   StWidget parent; | ||||
|  | ||||
|   StBoxLayoutPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _StBoxLayoutClass | ||||
| { | ||||
|   StWidgetClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType st_box_layout_get_type (void); | ||||
|  | ||||
| StWidget *st_box_layout_new (void); | ||||
|  | ||||
| void     st_box_layout_set_vertical   (StBoxLayout *box, | ||||
|                                        gboolean     vertical); | ||||
| gboolean st_box_layout_get_vertical   (StBoxLayout *box); | ||||
|  | ||||
| void     st_box_layout_set_pack_start (StBoxLayout *box, | ||||
|                                        gboolean     pack_start); | ||||
| gboolean st_box_layout_get_pack_start (StBoxLayout *box); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* _ST_BOX_LAYOUT_H */ | ||||
							
								
								
									
										693
									
								
								src/st/st-button.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										693
									
								
								src/st/st-button.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,693 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-button.c: 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. | ||||
|  * | ||||
|  * Written by: Emmanuele Bassi <ebassi@openedhand.com> | ||||
|  *             Thomas Wood <thomas@linux.intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:st-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 "st-button.h" | ||||
|  | ||||
| #include "st-marshal.h" | ||||
| #include "st-texture-frame.h" | ||||
| #include "st-texture-cache.h" | ||||
| #include "st-private.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_LABEL, | ||||
|   PROP_TOGGLE_MODE, | ||||
|   PROP_CHECKED, | ||||
|   PROP_TRANSITION_DURATION | ||||
| }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   CLICKED, | ||||
|  | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| #define ST_BUTTON_GET_PRIVATE(obj)    \ | ||||
|   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_BUTTON, StButtonPrivate)) | ||||
|  | ||||
| struct _StButtonPrivate | ||||
| { | ||||
|   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 (StButton, st_button, ST_TYPE_BIN); | ||||
|  | ||||
| static void | ||||
| st_button_update_label_style (StButton *button) | ||||
| { | ||||
|   ClutterActor *label; | ||||
|   StThemeNode *theme_node; | ||||
|   ClutterColor color; | ||||
|   const PangoFontDescription *font; | ||||
|   gchar *font_string = NULL; | ||||
|  | ||||
|   label = st_bin_get_child ((StBin*) button); | ||||
|  | ||||
|   /* check the child is really a label */ | ||||
|   if (!CLUTTER_IS_TEXT (label)) | ||||
|     return; | ||||
|  | ||||
|   theme_node = st_widget_get_theme_node (ST_WIDGET (button)); | ||||
|  | ||||
|   st_theme_node_get_foreground_color (theme_node, &color); | ||||
|   clutter_text_set_color (CLUTTER_TEXT (label), &color); | ||||
|  | ||||
|   font = st_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 | ||||
| st_button_dispose_old_bg (StButton *button) | ||||
| { | ||||
|   StButtonPrivate *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 | ||||
| st_animation_completed (ClutterAnimation *animation, | ||||
|                         StButton         *button) | ||||
| { | ||||
|   st_button_dispose_old_bg (button); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_style_changed (StWidget *widget) | ||||
| { | ||||
|   StButton *button = ST_BUTTON (widget); | ||||
|   StButtonPrivate *priv = button->priv; | ||||
|   StButtonClass *button_class = ST_BUTTON_GET_CLASS (button); | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (button)); | ||||
|   ClutterActor *bg_image; | ||||
|   double spacing; | ||||
|  | ||||
|   st_button_dispose_old_bg (button); | ||||
|  | ||||
|   bg_image = st_widget_get_border_image ((StWidget*) button); | ||||
|   if (bg_image) | ||||
|     button->priv->old_bg = g_object_ref (bg_image); | ||||
|  | ||||
|   ST_WIDGET_CLASS (st_button_parent_class)->style_changed (widget); | ||||
|  | ||||
|   spacing = 6; | ||||
|   st_theme_node_get_length (theme_node, "border-spacing", FALSE, &spacing); | ||||
|   priv->spacing = round (spacing); | ||||
|  | ||||
|   /* update the label styling */ | ||||
|   st_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 && | ||||
|           (!st_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 (st_animation_completed), button); | ||||
|             } | ||||
|           else | ||||
|             { | ||||
|               st_button_dispose_old_bg (button); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_real_pressed (StButton *button) | ||||
| { | ||||
|   st_widget_set_style_pseudo_class ((StWidget*) button, "active"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_real_released (StButton *button) | ||||
| { | ||||
|   StButtonPrivate *priv = button->priv; | ||||
|  | ||||
|   if (priv->is_checked) | ||||
|     st_widget_set_style_pseudo_class ((StWidget*) button, "checked"); | ||||
|   else if (!priv->is_hover) | ||||
|     st_widget_set_style_pseudo_class ((StWidget*) button, NULL); | ||||
|   else | ||||
|     st_widget_set_style_pseudo_class ((StWidget*) button, "hover"); | ||||
|  | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| st_button_button_press (ClutterActor       *actor, | ||||
|                         ClutterButtonEvent *event) | ||||
| { | ||||
|   st_widget_hide_tooltip (ST_WIDGET (actor)); | ||||
|  | ||||
|   if (event->button == 1) | ||||
|     { | ||||
|       StButton *button = ST_BUTTON (actor); | ||||
|       StButtonClass *klass = ST_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 | ||||
| st_button_button_release (ClutterActor       *actor, | ||||
|                           ClutterButtonEvent *event) | ||||
| { | ||||
|   if (event->button == 1) | ||||
|     { | ||||
|       StButton *button = ST_BUTTON (actor); | ||||
|       StButtonClass *klass = ST_BUTTON_GET_CLASS (button); | ||||
|  | ||||
|       if (!button->priv->is_pressed) | ||||
|         return FALSE; | ||||
|  | ||||
|       clutter_ungrab_pointer (); | ||||
|  | ||||
|       if (button->priv->is_toggle) | ||||
|         { | ||||
|           st_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 | ||||
| st_button_enter (ClutterActor         *actor, | ||||
|                  ClutterCrossingEvent *event) | ||||
| { | ||||
|   StButton *button = ST_BUTTON (actor); | ||||
|  | ||||
|   if (!button->priv->is_checked) | ||||
|     st_widget_set_style_pseudo_class ((StWidget*) button, "hover"); | ||||
|  | ||||
|   button->priv->is_hover = 1; | ||||
|  | ||||
|   return CLUTTER_ACTOR_CLASS (st_button_parent_class)->enter_event (actor, event); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| st_button_leave (ClutterActor         *actor, | ||||
|                  ClutterCrossingEvent *event) | ||||
| { | ||||
|   StButton *button = ST_BUTTON (actor); | ||||
|  | ||||
|   button->priv->is_hover = 0; | ||||
|  | ||||
|   if (button->priv->is_pressed) | ||||
|     { | ||||
|       StButtonClass *klass = ST_BUTTON_GET_CLASS (button); | ||||
|  | ||||
|       clutter_ungrab_pointer (); | ||||
|  | ||||
|       button->priv->is_pressed = FALSE; | ||||
|  | ||||
|       if (klass->released) | ||||
|         klass->released (button); | ||||
|     } | ||||
|  | ||||
|   if (button->priv->is_checked) | ||||
|     st_widget_set_style_pseudo_class ((StWidget*) button, "checked"); | ||||
|   else | ||||
|     st_widget_set_style_pseudo_class ((StWidget*) button, NULL); | ||||
|  | ||||
|   return CLUTTER_ACTOR_CLASS (st_button_parent_class)->leave_event (actor, event); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_set_property (GObject      *gobject, | ||||
|                         guint         prop_id, | ||||
|                         const GValue *value, | ||||
|                         GParamSpec   *pspec) | ||||
| { | ||||
|   StButton *button = ST_BUTTON (gobject); | ||||
|   StButtonPrivate *priv = ST_BUTTON (gobject)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_LABEL: | ||||
|       st_button_set_label (button, g_value_get_string (value)); | ||||
|       break; | ||||
|     case PROP_TOGGLE_MODE: | ||||
|       st_button_set_toggle_mode (button, g_value_get_boolean (value)); | ||||
|       break; | ||||
|     case PROP_CHECKED: | ||||
|       st_button_set_checked (button, g_value_get_boolean (value)); | ||||
|       break; | ||||
|     case PROP_TRANSITION_DURATION: | ||||
|       priv->transition_duration = g_value_get_int (value); | ||||
|       break; | ||||
|  | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_get_property (GObject    *gobject, | ||||
|                         guint       prop_id, | ||||
|                         GValue     *value, | ||||
|                         GParamSpec *pspec) | ||||
| { | ||||
|   StButtonPrivate *priv = ST_BUTTON (gobject)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_LABEL: | ||||
|       g_value_set_string (value, priv->text); | ||||
|       break; | ||||
|     case PROP_TOGGLE_MODE: | ||||
|       g_value_set_boolean (value, priv->is_toggle); | ||||
|       break; | ||||
|     case PROP_CHECKED: | ||||
|       g_value_set_boolean (value, priv->is_checked); | ||||
|       break; | ||||
|     case PROP_TRANSITION_DURATION: | ||||
|       g_value_set_int (value, priv->transition_duration); | ||||
|       break; | ||||
|  | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_finalize (GObject *gobject) | ||||
| { | ||||
|   StButtonPrivate *priv = ST_BUTTON (gobject)->priv; | ||||
|  | ||||
|   g_free (priv->text); | ||||
|  | ||||
|   G_OBJECT_CLASS (st_button_parent_class)->finalize (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_dispose (GObject *gobject) | ||||
| { | ||||
|   st_button_dispose_old_bg (ST_BUTTON (gobject)); | ||||
|  | ||||
|   G_OBJECT_CLASS (st_button_parent_class)->dispose (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_map (ClutterActor *self) | ||||
| { | ||||
|   StButtonPrivate *priv = ST_BUTTON (self)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (st_button_parent_class)->map (self); | ||||
|  | ||||
|   if (priv->old_bg && priv->old_bg_parented) | ||||
|     clutter_actor_map (priv->old_bg); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_unmap (ClutterActor *self) | ||||
| { | ||||
|   StButtonPrivate *priv = ST_BUTTON (self)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (st_button_parent_class)->unmap (self); | ||||
|  | ||||
|   if (priv->old_bg && priv->old_bg_parented) | ||||
|     clutter_actor_unmap (priv->old_bg); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_draw_background (StWidget         *widget) | ||||
| { | ||||
|   StButtonPrivate *priv; | ||||
|  | ||||
|   ST_WIDGET_CLASS (st_button_parent_class)->draw_background (widget); | ||||
|  | ||||
|   priv = ST_BUTTON (widget)->priv; | ||||
|  | ||||
|   if (priv->old_bg && priv->old_bg_parented) | ||||
|     clutter_actor_paint (priv->old_bg); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_class_init (StButtonClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   StWidgetClass *widget_class = ST_WIDGET_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (StButtonPrivate)); | ||||
|  | ||||
|   klass->pressed = st_button_real_pressed; | ||||
|   klass->released = st_button_real_released; | ||||
|  | ||||
|   gobject_class->set_property = st_button_set_property; | ||||
|   gobject_class->get_property = st_button_get_property; | ||||
|   gobject_class->dispose = st_button_dispose; | ||||
|   gobject_class->finalize = st_button_finalize; | ||||
|  | ||||
|   actor_class->button_press_event = st_button_button_press; | ||||
|   actor_class->button_release_event = st_button_button_release; | ||||
|   actor_class->enter_event = st_button_enter; | ||||
|   actor_class->leave_event = st_button_leave; | ||||
|  | ||||
|   actor_class->map = st_button_map; | ||||
|   actor_class->unmap = st_button_unmap; | ||||
|  | ||||
|   widget_class->draw_background = st_button_draw_background; | ||||
|   widget_class->style_changed = st_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_MODE, 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_CHECKED, 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_DURATION, pspec); | ||||
|  | ||||
|  | ||||
|   /** | ||||
|    * StButton::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 (StButtonClass, clicked), | ||||
|                   NULL, NULL, | ||||
|                   _st_marshal_VOID__VOID, | ||||
|                   G_TYPE_NONE, 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_button_init (StButton *button) | ||||
| { | ||||
|   button->priv = ST_BUTTON_GET_PRIVATE (button); | ||||
|   button->priv->transition_duration = 120; | ||||
|   button->priv->spacing = 6; | ||||
|  | ||||
|   clutter_actor_set_reactive ((ClutterActor *) button, TRUE); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_button_new: | ||||
|  * | ||||
|  * Create a new button | ||||
|  * | ||||
|  * Returns: a new #StButton | ||||
|  */ | ||||
| StWidget * | ||||
| st_button_new (void) | ||||
| { | ||||
|   return g_object_new (ST_TYPE_BUTTON, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_button_new_with_label: | ||||
|  * @text: text to set the label to | ||||
|  * | ||||
|  * Create a new #StButton with the specified label | ||||
|  * | ||||
|  * Returns: a new #StButton | ||||
|  */ | ||||
| StWidget * | ||||
| st_button_new_with_label (const gchar *text) | ||||
| { | ||||
|   return g_object_new (ST_TYPE_BUTTON, "label", text, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_button_get_label: | ||||
|  * @button: a #StButton | ||||
|  * | ||||
|  * 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 * | ||||
| st_button_get_label (StButton *button) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_BUTTON (button), NULL); | ||||
|  | ||||
|   return button->priv->text; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_button_set_label: | ||||
|  * @button: a #Stbutton | ||||
|  * @text: text to set the label to | ||||
|  * | ||||
|  * Sets the text displayed on the button | ||||
|  */ | ||||
| void | ||||
| st_button_set_label (StButton    *button, | ||||
|                      const gchar *text) | ||||
| { | ||||
|   StButtonPrivate *priv; | ||||
|   ClutterActor *label; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_BUTTON (button)); | ||||
|  | ||||
|   priv = button->priv; | ||||
|  | ||||
|   g_free (priv->text); | ||||
|  | ||||
|   if (text) | ||||
|     priv->text = g_strdup (text); | ||||
|   else | ||||
|     priv->text = g_strdup (""); | ||||
|  | ||||
|   label = st_bin_get_child ((StBin*) 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); | ||||
|       st_bin_set_child ((StBin*) button, label); | ||||
|     } | ||||
|  | ||||
|   /* Fake a style change so that we reset the style properties on the label */ | ||||
|   st_widget_style_changed (ST_WIDGET (button)); | ||||
|  | ||||
|   g_object_notify (G_OBJECT (button), "label"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_button_get_toggle_mode: | ||||
|  * @button: a #StButton | ||||
|  * | ||||
|  * Get the toggle mode status of the button. | ||||
|  * | ||||
|  * Returns: #TRUE if toggle mode is set, otherwise #FALSE | ||||
|  */ | ||||
| gboolean | ||||
| st_button_get_toggle_mode (StButton *button) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_BUTTON (button), FALSE); | ||||
|  | ||||
|   return button->priv->is_toggle; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_button_set_toggle_mode: | ||||
|  * @button: a #Stbutton | ||||
|  * @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 | ||||
| st_button_set_toggle_mode (StButton *button, | ||||
|                            gboolean  toggle) | ||||
| { | ||||
|   g_return_if_fail (ST_IS_BUTTON (button)); | ||||
|  | ||||
|   button->priv->is_toggle = toggle; | ||||
|  | ||||
|   g_object_notify (G_OBJECT (button), "toggle-mode"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_button_get_checked: | ||||
|  * @button: a #StButton | ||||
|  * | ||||
|  * Get the state of the button that is in toggle mode. | ||||
|  * | ||||
|  * Returns: #TRUE if the button is checked, or #FALSE if not | ||||
|  */ | ||||
| gboolean | ||||
| st_button_get_checked (StButton *button) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_BUTTON (button), FALSE); | ||||
|  | ||||
|   return button->priv->is_checked; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_button_set_checked: | ||||
|  * @button: a #Stbutton | ||||
|  * @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 | ||||
| st_button_set_checked (StButton *button, | ||||
|                        gboolean  checked) | ||||
| { | ||||
|   g_return_if_fail (ST_IS_BUTTON (button)); | ||||
|  | ||||
|   if (button->priv->is_checked != checked) | ||||
|     { | ||||
|       button->priv->is_checked = checked; | ||||
|  | ||||
|       if (checked) | ||||
|         st_widget_set_style_pseudo_class ((StWidget*) button, "checked"); | ||||
|       else | ||||
|       if (button->priv->is_hover) | ||||
|         st_widget_set_style_pseudo_class ((StWidget*) button, "hover"); | ||||
|       else | ||||
|         st_widget_set_style_pseudo_class ((StWidget*) button, NULL); | ||||
|     } | ||||
|  | ||||
|   g_object_notify (G_OBJECT (button), "checked"); | ||||
| } | ||||
							
								
								
									
										94
									
								
								src/st/st-button.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/st/st-button.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_BUTTON_H__ | ||||
| #define __ST_BUTTON_H__ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #include <st/st-bin.h> | ||||
|  | ||||
| #define ST_TYPE_BUTTON                (st_button_get_type ()) | ||||
| #define ST_BUTTON(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_BUTTON, StButton)) | ||||
| #define ST_IS_BUTTON(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_BUTTON)) | ||||
| #define ST_BUTTON_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_BUTTON, StButtonClass)) | ||||
| #define ST_IS_BUTTON_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_BUTTON)) | ||||
| #define ST_BUTTON_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_BUTTON, StButtonClass)) | ||||
|  | ||||
| typedef struct _StButton              StButton; | ||||
| typedef struct _StButtonPrivate       StButtonPrivate; | ||||
| typedef struct _StButtonClass         StButtonClass; | ||||
|  | ||||
| /** | ||||
|  * StButton: | ||||
|  * | ||||
|  * The contents of this structure is private and should only be accessed using | ||||
|  * the provided API. | ||||
|  */ | ||||
|  | ||||
| struct _StButton | ||||
| { | ||||
|   /*< private >*/ | ||||
|   StBin parent_instance; | ||||
|  | ||||
|   StButtonPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _StButtonClass | ||||
| { | ||||
|   StBinClass parent_class; | ||||
|  | ||||
|   /* vfuncs, not signals */ | ||||
|   void (* pressed)    (StButton     *button); | ||||
|   void (* released)   (StButton     *button); | ||||
|   void (* transition) (StButton     *button, | ||||
|                        ClutterActor *old_bg); | ||||
|  | ||||
|   /* signals */ | ||||
|   void (* clicked) (StButton *button); | ||||
| }; | ||||
|  | ||||
| GType st_button_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| StWidget *            st_button_new             (void); | ||||
| StWidget *            st_button_new_with_label  (const gchar *text); | ||||
| G_CONST_RETURN gchar *st_button_get_label       (StButton    *button); | ||||
| void                  st_button_set_label       (StButton    *button, | ||||
|                                                  const gchar *text); | ||||
| void                  st_button_set_toggle_mode (StButton    *button, | ||||
|                                                  gboolean     toggle); | ||||
| gboolean              st_button_get_toggle_mode (StButton    *button); | ||||
| void                  st_button_set_checked     (StButton    *button, | ||||
|                                                  gboolean     checked); | ||||
| gboolean              st_button_get_checked     (StButton    *button); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_BUTTON_H__ */ | ||||
							
								
								
									
										381
									
								
								src/st/st-clipboard.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										381
									
								
								src/st/st-clipboard.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,381 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:st-clipboard | ||||
|  * @short_description: a simple representation of the X clipboard | ||||
|  * | ||||
|  * #StCliboard is a very simple object representation of the clipboard | ||||
|  * available to applications. Text is always assumed to be UTF-8 and non-text | ||||
|  * items are not handled. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include "st-clipboard.h" | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/Xatom.h> | ||||
| #include <clutter/x11/clutter-x11.h> | ||||
| #include <string.h> | ||||
|  | ||||
| G_DEFINE_TYPE (StClipboard, st_clipboard, G_TYPE_OBJECT) | ||||
|  | ||||
| #define CLIPBOARD_PRIVATE(o) \ | ||||
|   (G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_CLIPBOARD, StClipboardPrivate)) | ||||
|  | ||||
| struct _StClipboardPrivate | ||||
| { | ||||
|   Window clipboard_window; | ||||
|   gchar *clipboard_text; | ||||
|  | ||||
|   Atom  *supported_targets; | ||||
|   gint   n_targets; | ||||
| }; | ||||
|  | ||||
| typedef struct _EventFilterData EventFilterData; | ||||
| struct _EventFilterData | ||||
| { | ||||
|   StClipboard            *clipboard; | ||||
|   StClipboardCallbackFunc callback; | ||||
|   gpointer                user_data; | ||||
| }; | ||||
|  | ||||
| static Atom __atom_clip = None; | ||||
| static Atom __utf8_string = None; | ||||
| static Atom __atom_targets = None; | ||||
|  | ||||
| static void | ||||
| st_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 | ||||
| st_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 | ||||
| st_clipboard_dispose (GObject *object) | ||||
| { | ||||
|   G_OBJECT_CLASS (st_clipboard_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_clipboard_finalize (GObject *object) | ||||
| { | ||||
|   StClipboardPrivate *priv = ((StClipboard *) 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 (st_clipboard_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static ClutterX11FilterReturn | ||||
| st_clipboard_provider (XEvent       *xev, | ||||
|                        ClutterEvent *cev, | ||||
|                        StClipboard  *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 | ||||
| st_clipboard_class_init (StClipboardClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (StClipboardPrivate)); | ||||
|  | ||||
|   object_class->get_property = st_clipboard_get_property; | ||||
|   object_class->set_property = st_clipboard_set_property; | ||||
|   object_class->dispose = st_clipboard_dispose; | ||||
|   object_class->finalize = st_clipboard_finalize; | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_clipboard_init (StClipboard *self) | ||||
| { | ||||
|   Display *dpy; | ||||
|   StClipboardPrivate *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) st_clipboard_provider, | ||||
|                           self); | ||||
| } | ||||
|  | ||||
| static ClutterX11FilterReturn | ||||
| st_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) st_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) st_clipboard_x11_event_filter, | ||||
|                           filter_data); | ||||
|  | ||||
|   g_free (filter_data); | ||||
|  | ||||
|   if (data) | ||||
|     XFree (data); | ||||
|  | ||||
|   return CLUTTER_X11_FILTER_REMOVE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_clipboard_get_default: | ||||
|  * | ||||
|  * Get the global #StClipboard object that represents the clipboard. | ||||
|  * | ||||
|  * Returns: (transfer none): a #StClipboard owned by St and must not be | ||||
|  * unrefferenced or freed. | ||||
|  */ | ||||
| StClipboard* | ||||
| st_clipboard_get_default (void) | ||||
| { | ||||
|   static StClipboard *default_clipboard = NULL; | ||||
|  | ||||
|   if (!default_clipboard) | ||||
|     { | ||||
|       default_clipboard = g_object_new (ST_TYPE_CLIPBOARD, NULL); | ||||
|     } | ||||
|  | ||||
|   return default_clipboard; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_clipboard_get_text: | ||||
|  * @clipboard: A #StCliboard | ||||
|  * @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 | ||||
| st_clipboard_get_text (StClipboard            *clipboard, | ||||
|                        StClipboardCallbackFunc callback, | ||||
|                        gpointer                user_data) | ||||
| { | ||||
|   EventFilterData *data; | ||||
|  | ||||
|   Display *dpy; | ||||
|  | ||||
|   g_return_if_fail (ST_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) st_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 (); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_clipboard_set_text: | ||||
|  * @clipboard: A #StClipboard | ||||
|  * @text: text to copy to the clipboard | ||||
|  * | ||||
|  * Sets text as the current contents of the clipboard. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_clipboard_set_text (StClipboard *clipboard, | ||||
|                        const gchar *text) | ||||
| { | ||||
|   StClipboardPrivate *priv; | ||||
|   Display *dpy; | ||||
|  | ||||
|   g_return_if_fail (ST_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 (); | ||||
| } | ||||
							
								
								
									
										103
									
								
								src/st/st-clipboard.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/st/st-clipboard.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef _ST_CLIPBOARD_H | ||||
| #define _ST_CLIPBOARD_H | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_CLIPBOARD st_clipboard_get_type() | ||||
|  | ||||
| #define ST_CLIPBOARD(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ | ||||
|   ST_TYPE_CLIPBOARD, StClipboard)) | ||||
|  | ||||
| #define ST_CLIPBOARD_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_CAST ((klass), \ | ||||
|   ST_TYPE_CLIPBOARD, StClipboardClass)) | ||||
|  | ||||
| #define ST_IS_CLIPBOARD(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ | ||||
|   ST_TYPE_CLIPBOARD)) | ||||
|  | ||||
| #define ST_IS_CLIPBOARD_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_TYPE ((klass), \ | ||||
|   ST_TYPE_CLIPBOARD)) | ||||
|  | ||||
| #define ST_CLIPBOARD_GET_CLASS(obj) \ | ||||
|   (G_TYPE_INSTANCE_GET_CLASS ((obj), \ | ||||
|   ST_TYPE_CLIPBOARD, StClipboardClass)) | ||||
|  | ||||
| typedef struct _StClipboard StClipboard; | ||||
| typedef struct _StClipboardClass StClipboardClass; | ||||
| typedef struct _StClipboardPrivate StClipboardPrivate; | ||||
|  | ||||
| /** | ||||
|  * StClipboard: | ||||
|  * | ||||
|  * The contents of this structure is private and should only be accessed using | ||||
|  * the provided API. | ||||
|  */ | ||||
| struct _StClipboard | ||||
| { | ||||
|   /*< private >*/ | ||||
|   GObject parent; | ||||
|   StClipboardPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _StClipboardClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * StClipboardCallbackFunc: | ||||
|  * @clipboard: A #StClipboard | ||||
|  * @text: text from the clipboard | ||||
|  * @user_data: user data | ||||
|  * | ||||
|  * Callback function called when text is retrieved from the clipboard. | ||||
|  */ | ||||
| typedef void (*StClipboardCallbackFunc) (StClipboard *clipboard, | ||||
|                                          const gchar *text, | ||||
|                                          gpointer     user_data); | ||||
|  | ||||
| GType st_clipboard_get_type (void); | ||||
|  | ||||
| StClipboard* st_clipboard_get_default (void); | ||||
|  | ||||
| void st_clipboard_get_text (StClipboard             *clipboard, | ||||
|                             StClipboardCallbackFunc  callback, | ||||
|                             gpointer                 user_data); | ||||
| void st_clipboard_set_text (StClipboard             *clipboard, | ||||
|                             const gchar             *text); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* _ST_CLIPBOARD_H */ | ||||
							
								
								
									
										899
									
								
								src/st/st-entry.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										899
									
								
								src/st/st-entry.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,899 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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:st-entry | ||||
|  * @short_description: Widget for displaying text | ||||
|  * | ||||
|  * #StEntry is a simple widget for displaying text. It derives from | ||||
|  * #StWidget to add extra style and placement functionality over | ||||
|  * #ClutterText. The internal #ClutterText is publicly accessibly to allow | ||||
|  * applications to set further properties. | ||||
|  * | ||||
|  * #StEntry 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 "st-entry.h" | ||||
|  | ||||
| #include "st-widget.h" | ||||
| #include "st-texture-cache.h" | ||||
| #include "st-marshal.h" | ||||
| #include "st-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 ST_ENTRY_GET_PRIVATE(obj)     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_ENTRY, StEntryPrivate)) | ||||
| #define ST_ENTRY_PRIV(x) ((StEntry *) x)->priv | ||||
|  | ||||
|  | ||||
| struct _StEntryPrivate | ||||
| { | ||||
|   ClutterActor *entry; | ||||
|   gchar        *hint; | ||||
|  | ||||
|   ClutterActor *primary_icon; | ||||
|   ClutterActor *secondary_icon; | ||||
|  | ||||
|   gfloat        spacing; | ||||
| }; | ||||
|  | ||||
| static guint entry_signals[LAST_SIGNAL] = { 0, }; | ||||
|  | ||||
| G_DEFINE_TYPE (StEntry, st_entry, ST_TYPE_WIDGET); | ||||
|  | ||||
| static void | ||||
| st_entry_set_property (GObject      *gobject, | ||||
|                        guint         prop_id, | ||||
|                        const GValue *value, | ||||
|                        GParamSpec   *pspec) | ||||
| { | ||||
|   StEntry *entry = ST_ENTRY (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_HINT_TEXT: | ||||
|       st_entry_set_hint_text (entry, g_value_get_string (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TEXT: | ||||
|       st_entry_set_text (entry, g_value_get_string (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_entry_get_property (GObject    *gobject, | ||||
|                        guint       prop_id, | ||||
|                        GValue     *value, | ||||
|                        GParamSpec *pspec) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_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 | ||||
| st_entry_dispose (GObject *object) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_ENTRY_PRIV (object); | ||||
|  | ||||
|   if (priv->entry) | ||||
|     { | ||||
|       clutter_actor_unparent (priv->entry); | ||||
|       priv->entry = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_entry_finalize (GObject *object) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_ENTRY_PRIV (object); | ||||
|  | ||||
|   g_free (priv->hint); | ||||
|   priv->hint = NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_entry_style_changed (StWidget *self) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_ENTRY_PRIV (self); | ||||
|   StThemeNode *theme_node; | ||||
|   ClutterColor color; | ||||
|   const PangoFontDescription *font; | ||||
|   gchar *font_string; | ||||
|  | ||||
|   theme_node = st_widget_get_theme_node (self); | ||||
|   | ||||
|   st_theme_node_get_foreground_color (theme_node, &color); | ||||
|   clutter_text_set_color (CLUTTER_TEXT (priv->entry), &color); | ||||
|  | ||||
|   if (st_theme_node_get_color (theme_node, "caret-color", FALSE, &color)) | ||||
|     clutter_text_set_cursor_color (CLUTTER_TEXT (priv->entry), &color); | ||||
|  | ||||
|   if (st_theme_node_get_color (theme_node, "selection-background-color", FALSE, &color)) | ||||
|     clutter_text_set_selection_color (CLUTTER_TEXT (priv->entry), &color); | ||||
|  | ||||
|   font = st_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); | ||||
|  | ||||
|   ST_WIDGET_CLASS (st_entry_parent_class)->style_changed (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_entry_get_preferred_width (ClutterActor *actor, | ||||
|                               gfloat        for_height, | ||||
|                               gfloat       *min_width_p, | ||||
|                               gfloat       *natural_width_p) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_ENTRY_PRIV (actor); | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); | ||||
|   gfloat icon_w; | ||||
|  | ||||
|   st_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; | ||||
|     } | ||||
|  | ||||
|   st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_entry_get_preferred_height (ClutterActor *actor, | ||||
|                                gfloat        for_width, | ||||
|                                gfloat       *min_height_p, | ||||
|                                gfloat       *natural_height_p) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_ENTRY_PRIV (actor); | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); | ||||
|   gfloat icon_h; | ||||
|  | ||||
|   st_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; | ||||
|     } | ||||
|  | ||||
|   st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_entry_allocate (ClutterActor          *actor, | ||||
|                    const ClutterActorBox *box, | ||||
|                    ClutterAllocationFlags flags) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_ENTRY_PRIV (actor); | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_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 (st_entry_parent_class); | ||||
|   parent_class->allocate (actor, box, flags); | ||||
|  | ||||
|   st_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) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_ENTRY_PRIV (actor); | ||||
|  | ||||
|   /* remove the hint if visible */ | ||||
|   if (priv->hint | ||||
|       && !strcmp (clutter_text_get_text (text), priv->hint)) | ||||
|     { | ||||
|       clutter_text_set_text (text, ""); | ||||
|     } | ||||
|   st_widget_set_style_pseudo_class (ST_WIDGET (actor), "focus"); | ||||
|   clutter_text_set_cursor_visible (text, TRUE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_text_focus_out_cb (ClutterText  *text, | ||||
|                            ClutterActor *actor) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_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); | ||||
|       st_widget_set_style_pseudo_class (ST_WIDGET (actor), "indeterminate"); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       st_widget_set_style_pseudo_class (ST_WIDGET (actor), NULL); | ||||
|     } | ||||
|   clutter_text_set_cursor_visible (text, FALSE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_entry_paint (ClutterActor *actor) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_ENTRY_PRIV (actor); | ||||
|   ClutterActorClass *parent_class; | ||||
|  | ||||
|   parent_class = CLUTTER_ACTOR_CLASS (st_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 | ||||
| st_entry_pick (ClutterActor       *actor, | ||||
|                const ClutterColor *c) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_ENTRY_PRIV (actor); | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (st_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 | ||||
| st_entry_map (ClutterActor *actor) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_ENTRY (actor)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (st_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 | ||||
| st_entry_unmap (ClutterActor *actor) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_ENTRY (actor)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (st_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 | ||||
| st_entry_clipboard_callback (StClipboard *clipboard, | ||||
|                              const gchar *text, | ||||
|                              gpointer     data) | ||||
| { | ||||
|   ClutterText *ctext = (ClutterText*)((StEntry *) 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 | ||||
| st_entry_key_press_event (ClutterActor    *actor, | ||||
|                           ClutterKeyEvent *event) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_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) | ||||
|     { | ||||
|       StClipboard *clipboard; | ||||
|  | ||||
|       clipboard = st_clipboard_get_default (); | ||||
|  | ||||
|       st_clipboard_get_text (clipboard, st_entry_clipboard_callback, actor); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   /* copy */ | ||||
|   if ((event->modifier_state & CLUTTER_CONTROL_MASK) | ||||
|       && event->keyval == CLUTTER_c) | ||||
|     { | ||||
|       StClipboard *clipboard; | ||||
|       gchar *text; | ||||
|  | ||||
|       clipboard = st_clipboard_get_default (); | ||||
|  | ||||
|       text = clutter_text_get_selection ((ClutterText*) priv->entry); | ||||
|  | ||||
|       if (text && strlen (text)) | ||||
|         st_clipboard_set_text (clipboard, text); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|  | ||||
|   /* cut */ | ||||
|   if ((event->modifier_state & CLUTTER_CONTROL_MASK) | ||||
|       && event->keyval == CLUTTER_x) | ||||
|     { | ||||
|       StClipboard *clipboard; | ||||
|       gchar *text; | ||||
|  | ||||
|       clipboard = st_clipboard_get_default (); | ||||
|  | ||||
|       text = clutter_text_get_selection ((ClutterText*) priv->entry); | ||||
|  | ||||
|       if (text && strlen (text)) | ||||
|         { | ||||
|           st_clipboard_set_text (clipboard, text); | ||||
|  | ||||
|           /* now delete the text */ | ||||
|           clutter_text_delete_selection ((ClutterText *) priv->entry); | ||||
|         } | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_entry_key_focus_in (ClutterActor *actor) | ||||
| { | ||||
|   StEntryPrivate *priv = ST_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 | ||||
| st_entry_class_init (StEntryClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   StWidgetClass *widget_class = ST_WIDGET_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (StEntryPrivate)); | ||||
|  | ||||
|   gobject_class->set_property = st_entry_set_property; | ||||
|   gobject_class->get_property = st_entry_get_property; | ||||
|   gobject_class->finalize = st_entry_finalize; | ||||
|   gobject_class->dispose = st_entry_dispose; | ||||
|  | ||||
|   actor_class->get_preferred_width = st_entry_get_preferred_width; | ||||
|   actor_class->get_preferred_height = st_entry_get_preferred_height; | ||||
|   actor_class->allocate = st_entry_allocate; | ||||
|   actor_class->paint = st_entry_paint; | ||||
|   actor_class->pick = st_entry_pick; | ||||
|   actor_class->map = st_entry_map; | ||||
|   actor_class->unmap = st_entry_unmap; | ||||
|  | ||||
|   actor_class->key_press_event = st_entry_key_press_event; | ||||
|   actor_class->key_focus_in = st_entry_key_focus_in; | ||||
|  | ||||
|   widget_class->style_changed = st_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 */ | ||||
|   /** | ||||
|    * StEntry::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 (StEntryClass, primary_icon_clicked), | ||||
|                   NULL, NULL, | ||||
|                   _st_marshal_VOID__VOID, | ||||
|                   G_TYPE_NONE, 0); | ||||
|   /** | ||||
|    * StEntry::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 (StEntryClass, secondary_icon_clicked), | ||||
|                   NULL, NULL, | ||||
|                   _st_marshal_VOID__VOID, | ||||
|                   G_TYPE_NONE, 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_entry_init (StEntry *entry) | ||||
| { | ||||
|   StEntryPrivate *priv; | ||||
|  | ||||
|   priv = entry->priv = ST_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); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_new: | ||||
|  * @text: text to set the entry to | ||||
|  * | ||||
|  * Create a new #StEntry with the specified entry | ||||
|  * | ||||
|  * Returns: a new #StEntry | ||||
|  */ | ||||
| StWidget * | ||||
| st_entry_new (const gchar *text) | ||||
| { | ||||
|   StWidget *entry; | ||||
|  | ||||
|   /* add the entry to the stage, but don't allow it to be visible */ | ||||
|   entry = g_object_new (ST_TYPE_ENTRY, | ||||
|                         "text", text, | ||||
|                         NULL); | ||||
|  | ||||
|   return entry; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_get_text: | ||||
|  * @entry: a #StEntry | ||||
|  * | ||||
|  * 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 * | ||||
| st_entry_get_text (StEntry *entry) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_ENTRY (entry), NULL); | ||||
|  | ||||
|   return clutter_text_get_text (CLUTTER_TEXT (entry->priv->entry)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_set_text: | ||||
|  * @entry: a #StEntry | ||||
|  * @text: text to set the entry to | ||||
|  * | ||||
|  * Sets the text displayed on the entry | ||||
|  */ | ||||
| void | ||||
| st_entry_set_text (StEntry     *entry, | ||||
|                    const gchar *text) | ||||
| { | ||||
|   StEntryPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_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; | ||||
|       st_widget_set_style_pseudo_class (ST_WIDGET (entry), "indeterminate"); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (HAS_FOCUS (priv->entry)) | ||||
|         st_widget_set_style_pseudo_class (ST_WIDGET (entry), "focus"); | ||||
|       else | ||||
|         st_widget_set_style_pseudo_class (ST_WIDGET (entry), NULL); | ||||
|     } | ||||
|  | ||||
|   clutter_text_set_text (CLUTTER_TEXT (priv->entry), text); | ||||
|  | ||||
|   g_object_notify (G_OBJECT (entry), "text"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_get_clutter_text: | ||||
|  * @entry: a #StEntry | ||||
|  * | ||||
|  * Retrieve the internal #ClutterText so that extra parameters can be set | ||||
|  * | ||||
|  * Returns: (transfer none): the #ClutterText used by #StEntry. The entry is | ||||
|  * owned by the #StEntry and should not be unref'ed by the application. | ||||
|  */ | ||||
| ClutterActor* | ||||
| st_entry_get_clutter_text (StEntry *entry) | ||||
| { | ||||
|   g_return_val_if_fail (ST_ENTRY (entry), NULL); | ||||
|  | ||||
|   return entry->priv->entry; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_set_hint_text: | ||||
|  * @entry: a #StEntry | ||||
|  * @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 | ||||
| st_entry_set_hint_text (StEntry     *entry, | ||||
|                         const gchar *text) | ||||
| { | ||||
|   StEntryPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_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); | ||||
|       st_widget_set_style_pseudo_class (ST_WIDGET (entry), "indeterminate"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_get_hint_text: | ||||
|  * @entry: a #StEntry | ||||
|  * | ||||
|  * 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 | ||||
|  * #StEntry and should not be freed or modified. | ||||
|  */ | ||||
| G_CONST_RETURN | ||||
| gchar * | ||||
| st_entry_get_hint_text (StEntry *entry) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_ENTRY (entry), NULL); | ||||
|  | ||||
|   return entry->priv->hint; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| _st_entry_icon_press_cb (ClutterActor       *actor, | ||||
|                          ClutterButtonEvent *event, | ||||
|                          StEntry            *entry) | ||||
| { | ||||
|   StEntryPrivate *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 | ||||
| _st_entry_set_icon_from_file (StEntry       *entry, | ||||
|                               ClutterActor **icon, | ||||
|                               const gchar   *filename) | ||||
| { | ||||
|   if (*icon) | ||||
|     { | ||||
|       g_signal_handlers_disconnect_by_func (*icon, | ||||
|                                             _st_entry_icon_press_cb, | ||||
|                                             entry); | ||||
|       clutter_actor_unparent (*icon); | ||||
|       *icon = NULL; | ||||
|     } | ||||
|  | ||||
|   if (filename) | ||||
|     { | ||||
|       StTextureCache *cache; | ||||
|  | ||||
|       cache = st_texture_cache_get_default (); | ||||
|  | ||||
|  | ||||
|  | ||||
|       *icon = (ClutterActor*) st_texture_cache_get_texture (cache, filename); | ||||
|  | ||||
|       clutter_actor_set_reactive (*icon, TRUE); | ||||
|       clutter_actor_set_parent (*icon, CLUTTER_ACTOR (entry)); | ||||
|       g_signal_connect (*icon, "button-release-event", | ||||
|                         G_CALLBACK (_st_entry_icon_press_cb), entry); | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_relayout (CLUTTER_ACTOR (entry)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_set_primary_icon_from_file: | ||||
|  * @entry: a #StEntry | ||||
|  * @filename: filename of an icon | ||||
|  * | ||||
|  * Set the primary icon of the entry to the given filename | ||||
|  */ | ||||
| void | ||||
| st_entry_set_primary_icon_from_file (StEntry     *entry, | ||||
|                                      const gchar *filename) | ||||
| { | ||||
|   StEntryPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_ENTRY (entry)); | ||||
|  | ||||
|   priv = entry->priv; | ||||
|  | ||||
|   _st_entry_set_icon_from_file (entry, &priv->primary_icon, filename); | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_set_secondary_icon_from_file: | ||||
|  * @entry: a #StEntry | ||||
|  * @filename: filename of an icon | ||||
|  * | ||||
|  * Set the primary icon of the entry to the given filename | ||||
|  */ | ||||
| void | ||||
| st_entry_set_secondary_icon_from_file (StEntry     *entry, | ||||
|                                        const gchar *filename) | ||||
| { | ||||
|   StEntryPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_ENTRY (entry)); | ||||
|  | ||||
|   priv = entry->priv; | ||||
|  | ||||
|   _st_entry_set_icon_from_file (entry, &priv->secondary_icon, filename); | ||||
|  | ||||
| } | ||||
|  | ||||
							
								
								
									
										89
									
								
								src/st/st-entry.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/st/st-entry.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_ENTRY_H__ | ||||
| #define __ST_ENTRY_H__ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #include <st/st-widget.h> | ||||
|  | ||||
| #define ST_TYPE_ENTRY                (st_entry_get_type ()) | ||||
| #define ST_ENTRY(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_ENTRY, StEntry)) | ||||
| #define ST_IS_ENTRY(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_ENTRY)) | ||||
| #define ST_ENTRY_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_ENTRY, StEntryClass)) | ||||
| #define ST_IS_ENTRY_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_ENTRY)) | ||||
| #define ST_ENTRY_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_ENTRY, StEntryClass)) | ||||
|  | ||||
| typedef struct _StEntry              StEntry; | ||||
| typedef struct _StEntryPrivate       StEntryPrivate; | ||||
| typedef struct _StEntryClass         StEntryClass; | ||||
|  | ||||
| /** | ||||
|  * StEntry: | ||||
|  * | ||||
|  * The contents of this structure is private and should only be accessed using | ||||
|  * the provided API. | ||||
|  */ | ||||
| struct _StEntry | ||||
| { | ||||
|   /*< private >*/ | ||||
|   StWidget parent_instance; | ||||
|  | ||||
|   StEntryPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _StEntryClass | ||||
| { | ||||
|   StWidgetClass parent_class; | ||||
|  | ||||
|   /* signals */ | ||||
|   void (*primary_icon_clicked)   (StEntry *entry); | ||||
|   void (*secondary_icon_clicked) (StEntry *entry); | ||||
| }; | ||||
|  | ||||
| GType st_entry_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| StWidget *            st_entry_new              (const gchar *text); | ||||
| G_CONST_RETURN gchar *st_entry_get_text         (StEntry     *entry); | ||||
| void                  st_entry_set_text         (StEntry     *entry, | ||||
|                                                  const gchar *text); | ||||
| ClutterActor*         st_entry_get_clutter_text (StEntry     *entry); | ||||
|  | ||||
| void                  st_entry_set_hint_text    (StEntry     *entry, | ||||
|                                                  const gchar *text); | ||||
| G_CONST_RETURN gchar *st_entry_get_hint_text    (StEntry     *entry); | ||||
|  | ||||
| void st_entry_set_primary_icon_from_file   (StEntry     *entry, | ||||
|                                             const gchar *filename); | ||||
| void st_entry_set_secondary_icon_from_file (StEntry     *entry, | ||||
|                                             const gchar *filename); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_ENTRY_H__ */ | ||||
							
								
								
									
										30
									
								
								src/st/st-enum-types.c.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/st/st-enum-types.c.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| /*** BEGIN file-header ***/ | ||||
| #include "st-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/st/st-enum-types.h.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/st/st-enum-types.h.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| /*** BEGIN file-header ***/ | ||||
| #if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_ENUM_TYPES_H__ | ||||
| #define __ST_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 /* !__ST_ENUM_TYPES_H__ */ | ||||
| /*** END file-tail ***/ | ||||
|  | ||||
| /*** BEGIN value-header ***/ | ||||
| GType @enum_name@_get_type (void) G_GNUC_CONST; | ||||
| #define ST_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) | ||||
|  | ||||
| /*** END value-header ***/ | ||||
							
								
								
									
										342
									
								
								src/st/st-label.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								src/st/st-label.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,342 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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:st-label | ||||
|  * @short_description: Widget for displaying text | ||||
|  * | ||||
|  * #StLabel is a simple widget for displaying text. It derives from | ||||
|  * #StWidget 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 "st-label.h" | ||||
|  | ||||
| #include "st-widget.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_CLUTTER_TEXT, | ||||
|   PROP_TEXT | ||||
| }; | ||||
|  | ||||
| #define ST_LABEL_GET_PRIVATE(obj)     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_LABEL, StLabelPrivate)) | ||||
|  | ||||
| struct _StLabelPrivate | ||||
| { | ||||
|   ClutterActor *label; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (StLabel, st_label, ST_TYPE_WIDGET); | ||||
|  | ||||
| static void | ||||
| st_label_set_property (GObject      *gobject, | ||||
|                        guint         prop_id, | ||||
|                        const GValue *value, | ||||
|                        GParamSpec   *pspec) | ||||
| { | ||||
|   StLabel *label = ST_LABEL (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_TEXT: | ||||
|       st_label_set_text (label, g_value_get_string (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_label_get_property (GObject    *gobject, | ||||
|                        guint       prop_id, | ||||
|                        GValue     *value, | ||||
|                        GParamSpec *pspec) | ||||
| { | ||||
|   StLabelPrivate *priv = ST_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 | ||||
| st_label_style_changed (StWidget *self) | ||||
| { | ||||
|   StLabelPrivate *priv; | ||||
|   StThemeNode *theme_node; | ||||
|   ClutterColor color; | ||||
|   const PangoFontDescription *font; | ||||
|   gchar *font_string; | ||||
|  | ||||
|   priv = ST_LABEL (self)->priv; | ||||
|   theme_node = st_widget_get_theme_node (self); | ||||
|   st_theme_node_get_foreground_color (theme_node, &color); | ||||
|   clutter_text_set_color (CLUTTER_TEXT (priv->label), &color); | ||||
|  | ||||
|   font = st_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); | ||||
|  | ||||
|   ST_WIDGET_CLASS (st_label_parent_class)->style_changed (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_label_get_preferred_width (ClutterActor *actor, | ||||
|                               gfloat        for_height, | ||||
|                               gfloat       *min_width_p, | ||||
|                               gfloat       *natural_width_p) | ||||
| { | ||||
|   StLabelPrivate *priv = ST_LABEL (actor)->priv; | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); | ||||
|  | ||||
|   st_theme_node_adjust_for_height (theme_node, &for_height); | ||||
|  | ||||
|   clutter_actor_get_preferred_width (priv->label, for_height, | ||||
|                                      min_width_p, | ||||
|                                      natural_width_p); | ||||
|  | ||||
|   st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_label_get_preferred_height (ClutterActor *actor, | ||||
|                                gfloat        for_width, | ||||
|                                gfloat       *min_height_p, | ||||
|                                gfloat       *natural_height_p) | ||||
| { | ||||
|   StLabelPrivate *priv = ST_LABEL (actor)->priv; | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); | ||||
|  | ||||
|   st_theme_node_adjust_for_width (theme_node, &for_width); | ||||
|  | ||||
|   clutter_actor_get_preferred_height (priv->label, for_width, | ||||
|                                       min_height_p, | ||||
|                                       natural_height_p); | ||||
|  | ||||
|   st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_label_allocate (ClutterActor          *actor, | ||||
|                    const ClutterActorBox *box, | ||||
|                    ClutterAllocationFlags flags) | ||||
| { | ||||
|   StLabelPrivate *priv = ST_LABEL (actor)->priv; | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); | ||||
|   ClutterActorClass *parent_class; | ||||
|   ClutterActorBox content_box; | ||||
|  | ||||
|   st_theme_node_get_content_box (theme_node, box, &content_box); | ||||
|  | ||||
|   parent_class = CLUTTER_ACTOR_CLASS (st_label_parent_class); | ||||
|   parent_class->allocate (actor, box, flags); | ||||
|  | ||||
|   clutter_actor_allocate (priv->label, &content_box, flags); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_label_paint (ClutterActor *actor) | ||||
| { | ||||
|   StLabelPrivate *priv = ST_LABEL (actor)->priv; | ||||
|   ClutterActorClass *parent_class; | ||||
|  | ||||
|   parent_class = CLUTTER_ACTOR_CLASS (st_label_parent_class); | ||||
|   parent_class->paint (actor); | ||||
|  | ||||
|   clutter_actor_paint (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_label_map (ClutterActor *actor) | ||||
| { | ||||
|   StLabelPrivate *priv = ST_LABEL (actor)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (st_label_parent_class)->map (actor); | ||||
|  | ||||
|   clutter_actor_map (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_label_unmap (ClutterActor *actor) | ||||
| { | ||||
|   StLabelPrivate *priv = ST_LABEL (actor)->priv; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (st_label_parent_class)->unmap (actor); | ||||
|  | ||||
|   clutter_actor_unmap (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_label_class_init (StLabelClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   StWidgetClass *widget_class = ST_WIDGET_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (StLabelPrivate)); | ||||
|  | ||||
|   gobject_class->set_property = st_label_set_property; | ||||
|   gobject_class->get_property = st_label_get_property; | ||||
|  | ||||
|   actor_class->paint = st_label_paint; | ||||
|   actor_class->allocate = st_label_allocate; | ||||
|   actor_class->get_preferred_width = st_label_get_preferred_width; | ||||
|   actor_class->get_preferred_height = st_label_get_preferred_height; | ||||
|   actor_class->map = st_label_map; | ||||
|   actor_class->unmap = st_label_unmap; | ||||
|  | ||||
|   widget_class->style_changed = st_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 | ||||
| st_label_init (StLabel *label) | ||||
| { | ||||
|   StLabelPrivate *priv; | ||||
|  | ||||
|   label->priv = priv = ST_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)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_label_new: | ||||
|  * @text: text to set the label to | ||||
|  * | ||||
|  * Create a new #StLabel with the specified label | ||||
|  * | ||||
|  * Returns: a new #StLabel | ||||
|  */ | ||||
| StWidget * | ||||
| st_label_new (const gchar *text) | ||||
| { | ||||
|   if (text == NULL || *text == '\0') | ||||
|     return g_object_new (ST_TYPE_LABEL, NULL); | ||||
|   else | ||||
|     return g_object_new (ST_TYPE_LABEL, | ||||
|                          "text", text, | ||||
|                          NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_label_get_text: | ||||
|  * @label: a #StLabel | ||||
|  * | ||||
|  * 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 * | ||||
| st_label_get_text (StLabel *label) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_LABEL (label), NULL); | ||||
|  | ||||
|   return clutter_text_get_text (CLUTTER_TEXT (label->priv->label)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_label_set_text: | ||||
|  * @label: a #StLabel | ||||
|  * @text: text to set the label to | ||||
|  * | ||||
|  * Sets the text displayed on the label | ||||
|  */ | ||||
| void | ||||
| st_label_set_text (StLabel     *label, | ||||
|                    const gchar *text) | ||||
| { | ||||
|   StLabelPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_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"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_label_get_clutter_text: | ||||
|  * @label: a #StLabel | ||||
|  * | ||||
|  * Retrieve the internal #ClutterText so that extra parameters can be set | ||||
|  * | ||||
|  * Returns: (transfer none): ethe #ClutterText used by #StLabel. The label | ||||
|  * is owned by the #StLabel and should not be unref'ed by the application. | ||||
|  */ | ||||
| ClutterActor* | ||||
| st_label_get_clutter_text (StLabel *label) | ||||
| { | ||||
|   g_return_val_if_fail (ST_LABEL (label), NULL); | ||||
|  | ||||
|   return label->priv->label; | ||||
| } | ||||
							
								
								
									
										76
									
								
								src/st/st-label.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/st/st-label.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_LABEL_H__ | ||||
| #define __ST_LABEL_H__ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #include <st/st-widget.h> | ||||
|  | ||||
| #define ST_TYPE_LABEL                (st_label_get_type ()) | ||||
| #define ST_LABEL(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_LABEL, StLabel)) | ||||
| #define ST_IS_LABEL(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_LABEL)) | ||||
| #define ST_LABEL_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_LABEL, StLabelClass)) | ||||
| #define ST_IS_LABEL_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_LABEL)) | ||||
| #define ST_LABEL_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_LABEL, StLabelClass)) | ||||
|  | ||||
| typedef struct _StLabel              StLabel; | ||||
| typedef struct _StLabelPrivate       StLabelPrivate; | ||||
| typedef struct _StLabelClass         StLabelClass; | ||||
|  | ||||
| /** | ||||
|  * StLabel: | ||||
|  * | ||||
|  * The contents of this structure is private and should only be accessed using | ||||
|  * the provided API. | ||||
|  */ | ||||
| struct _StLabel | ||||
| { | ||||
|   /*< private >*/ | ||||
|   StWidget parent_instance; | ||||
|  | ||||
|   StLabelPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _StLabelClass | ||||
| { | ||||
|   StWidgetClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType st_label_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| StWidget *            st_label_new              (const gchar *text); | ||||
| G_CONST_RETURN gchar *st_label_get_text         (StLabel     *label); | ||||
| void                  st_label_set_text         (StLabel     *label, | ||||
|                                                  const gchar *text); | ||||
| ClutterActor *        st_label_get_clutter_text (StLabel     *label); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_LABEL_H__ */ | ||||
							
								
								
									
										12
									
								
								src/st/st-marshal.list
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/st/st-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 | ||||
							
								
								
									
										112
									
								
								src/st/st-private.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/st/st-private.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| #include "st-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 | ||||
| _st_allocate_fill (ClutterActor    *child, | ||||
|                    ClutterActorBox *childbox, | ||||
|                    StAlign          x_alignment, | ||||
|                    StAlign          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 == ST_ALIGN_START) | ||||
|     x_align = 0.0; | ||||
|   else if (x_alignment == ST_ALIGN_MIDDLE) | ||||
|     x_align = 0.5; | ||||
|   else | ||||
|     x_align = 1.0; | ||||
|  | ||||
|   if (y_alignment == ST_ALIGN_START) | ||||
|     y_align = 0.0; | ||||
|   else if (y_alignment == ST_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; | ||||
|  | ||||
| } | ||||
							
								
								
									
										58
									
								
								src/st/st-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/st/st-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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 __ST_PRIVATE_H__ | ||||
| #define __ST_PRIVATE_H__ | ||||
|  | ||||
| #include <glib.h> | ||||
| #include "st-widget.h" | ||||
| #include "st-bin.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define I_(str)         (g_intern_static_string ((str))) | ||||
|  | ||||
| #define ST_PARAM_READABLE     \ | ||||
|         (G_PARAM_READABLE |     \ | ||||
|          G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB) | ||||
|  | ||||
| #define ST_PARAM_READWRITE    \ | ||||
|         (G_PARAM_READABLE | G_PARAM_WRITABLE | \ | ||||
|          G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB) | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| ClutterActor *_st_widget_get_dnd_clone (StWidget *widget); | ||||
|  | ||||
| void _st_bin_get_align_factors (StBin   *bin, | ||||
|                                 gdouble *x_align, | ||||
|                                 gdouble *y_align); | ||||
|  | ||||
| void _st_allocate_fill (ClutterActor    *child, | ||||
|                         ClutterActorBox *childbox, | ||||
|                         StAlign          x_align, | ||||
|                         StAlign          y_align, | ||||
|                         gboolean         x_fill, | ||||
|                         gboolean         y_fill); | ||||
|  | ||||
| #endif /* __ST_PRIVATE_H__ */ | ||||
							
								
								
									
										1077
									
								
								src/st/st-scroll-bar.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1077
									
								
								src/st/st-scroll-bar.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										83
									
								
								src/st/st-scroll-bar.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/st/st-scroll-bar.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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 St by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_SCROLL_BAR_H__ | ||||
| #define __ST_SCROLL_BAR_H__ | ||||
|  | ||||
| #include <st/st-adjustment.h> | ||||
| #include <st/st-bin.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_SCROLL_BAR            (st_scroll_bar_get_type()) | ||||
| #define ST_SCROLL_BAR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_SCROLL_BAR, StScrollBar)) | ||||
| #define ST_IS_SCROLL_BAR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_SCROLL_BAR)) | ||||
| #define ST_SCROLL_BAR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_SCROLL_BAR, StScrollBarClass)) | ||||
| #define ST_IS_SCROLL_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_SCROLL_BAR)) | ||||
| #define ST_SCROLL_BAR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_SCROLL_BAR, StScrollBarClass)) | ||||
|  | ||||
| typedef struct _StScrollBar          StScrollBar; | ||||
| typedef struct _StScrollBarPrivate   StScrollBarPrivate; | ||||
| typedef struct _StScrollBarClass     StScrollBarClass; | ||||
|  | ||||
| /** | ||||
|  * StScrollBar: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _StScrollBar | ||||
| { | ||||
|   /*< private >*/ | ||||
|   StBin parent_instance; | ||||
|  | ||||
|   StScrollBarPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _StScrollBarClass | ||||
| { | ||||
|   StBinClass parent_class; | ||||
|  | ||||
|   /* signals */ | ||||
|   void (*scroll_start) (StScrollBar *bar); | ||||
|   void (*scroll_stop)  (StScrollBar *bar); | ||||
| }; | ||||
|  | ||||
| GType st_scroll_bar_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| StWidget *st_scroll_bar_new (StAdjustment *adjustment); | ||||
|  | ||||
| void          st_scroll_bar_set_adjustment (StScrollBar  *bar, | ||||
|                                             StAdjustment *adjustment); | ||||
| StAdjustment *st_scroll_bar_get_adjustment (StScrollBar  *bar); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_SCROLL_BAR_H__ */ | ||||
							
								
								
									
										844
									
								
								src/st/st-scroll-view.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										844
									
								
								src/st/st-scroll-view.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,844 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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 St by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:st-scroll-view | ||||
|  * @short_description: a container for scrollable children | ||||
|  * | ||||
|  * #StScrollView is a single child container for actors that implement | ||||
|  * #StScrollable. It provides scrollbars around the edge of the child to | ||||
|  * allow the user to move around the scrollable area. | ||||
|  */ | ||||
|  | ||||
| #include "st-scroll-view.h" | ||||
| #include "st-marshal.h" | ||||
| #include "st-scroll-bar.h" | ||||
| #include "st-scrollable.h" | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| static void clutter_container_iface_init (ClutterContainerIface *iface); | ||||
|  | ||||
| static ClutterContainerIface *st_scroll_view_parent_iface = NULL; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (StScrollView, st_scroll_view, ST_TYPE_BIN, | ||||
|                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, | ||||
|                                                 clutter_container_iface_init)) | ||||
|  | ||||
| #define SCROLL_VIEW_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ | ||||
|                                                              ST_TYPE_SCROLL_VIEW, \ | ||||
|                                                              StScrollViewPrivate)) | ||||
|  | ||||
| /* Default width (or height - the narrow dimension) for the scrollbars*/ | ||||
| #define DEFAULT_SCROLLBAR_WIDTH 24 | ||||
|  | ||||
| struct _StScrollViewPrivate | ||||
| { | ||||
|   /* a pointer to the child; this is actually stored | ||||
|    * inside StBin:child, but we keep it to avoid | ||||
|    * calling st_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 | ||||
| st_scroll_view_get_property (GObject    *object, | ||||
|                              guint       property_id, | ||||
|                              GValue     *value, | ||||
|                              GParamSpec *pspec) | ||||
| { | ||||
|   StScrollViewPrivate *priv = ((StScrollView *) 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 | ||||
| st_scroll_view_set_property (GObject      *object, | ||||
|                              guint         property_id, | ||||
|                              const GValue *value, | ||||
|                              GParamSpec   *pspec) | ||||
| { | ||||
|   switch (property_id) | ||||
|     { | ||||
|     case PROP_MOUSE_SCROLL: | ||||
|       st_scroll_view_set_mouse_scrolling ((StScrollView *) object, | ||||
|                                           g_value_get_boolean (value)); | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_scroll_view_dispose (GObject *object) | ||||
| { | ||||
|   StScrollViewPrivate *priv = ST_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 (st_scroll_view_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_scroll_view_finalize (GObject *object) | ||||
| { | ||||
|   G_OBJECT_CLASS (st_scroll_view_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_scroll_view_paint (ClutterActor *actor) | ||||
| { | ||||
|   StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv; | ||||
|  | ||||
|   /* StBin will paint the child */ | ||||
|   CLUTTER_ACTOR_CLASS (st_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 | ||||
| st_scroll_view_pick (ClutterActor       *actor, | ||||
|                      const ClutterColor *color) | ||||
| { | ||||
|   StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv; | ||||
|  | ||||
|   /* Chain up so we get a bounding box pained (if we are reactive) */ | ||||
|   CLUTTER_ACTOR_CLASS (st_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 (StScrollView *scroll_view) | ||||
| { | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (scroll_view)); | ||||
|   double result = DEFAULT_SCROLLBAR_WIDTH; | ||||
|  | ||||
|   st_theme_node_get_length (theme_node, "scrollbar-width", FALSE, &result); | ||||
|  | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| static double | ||||
| get_scrollbar_height (StScrollView *scroll_view) | ||||
| { | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (scroll_view)); | ||||
|   double result = DEFAULT_SCROLLBAR_WIDTH; | ||||
|  | ||||
|   st_theme_node_get_length (theme_node, "scrollbar-height", FALSE, &result); | ||||
|  | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_scroll_view_get_preferred_width (ClutterActor *actor, | ||||
|                                     gfloat        for_height, | ||||
|                                     gfloat       *min_width_p, | ||||
|                                     gfloat       *natural_width_p) | ||||
| { | ||||
|   StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv; | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); | ||||
|  | ||||
|   if (!priv->child) | ||||
|     return; | ||||
|  | ||||
|   st_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 (ST_SCROLL_VIEW (actor)); | ||||
|     } | ||||
|  | ||||
|   if (min_width_p) | ||||
|     *min_width_p = 0; | ||||
|  | ||||
|   st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_scroll_view_get_preferred_height (ClutterActor *actor, | ||||
|                                      gfloat        for_width, | ||||
|                                      gfloat       *min_height_p, | ||||
|                                      gfloat       *natural_height_p) | ||||
| { | ||||
|   StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv; | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); | ||||
|  | ||||
|   if (!priv->child) | ||||
|     return; | ||||
|  | ||||
|   st_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 (ST_SCROLL_VIEW (actor)); | ||||
|     } | ||||
|  | ||||
|   if (min_height_p) | ||||
|     *min_height_p = 0; | ||||
|  | ||||
|   st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_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; | ||||
|  | ||||
|   StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv; | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); | ||||
|  | ||||
|   /* Chain up to the parent's parent class | ||||
|    * | ||||
|    * We do this because we do not want StBin 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 (st_scroll_view_parent_class); | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (parent_parent_class)-> | ||||
|   allocate (actor, box, flags); | ||||
|  | ||||
|  | ||||
|   st_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 (ST_SCROLL_VIEW (actor)); | ||||
|   sb_height = get_scrollbar_width (ST_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 | ||||
| st_scroll_view_style_changed (StWidget *widget) | ||||
| { | ||||
|   StScrollViewPrivate *priv = ST_SCROLL_VIEW (widget)->priv; | ||||
|  | ||||
|   st_widget_style_changed (ST_WIDGET (priv->hscroll)); | ||||
|   st_widget_style_changed (ST_WIDGET (priv->vscroll)); | ||||
|  | ||||
|   ST_WIDGET_CLASS (st_scroll_view_parent_class)->style_changed (widget); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| st_scroll_view_scroll_event (ClutterActor       *self, | ||||
|                              ClutterScrollEvent *event) | ||||
| { | ||||
|   StScrollViewPrivate *priv = ST_SCROLL_VIEW (self)->priv; | ||||
|   gdouble lower, value, upper, step; | ||||
|   StAdjustment *vadjustment, *hadjustment; | ||||
|  | ||||
|   /* don't handle scroll events if requested not to */ | ||||
|   if (!priv->mouse_scroll) | ||||
|     return FALSE; | ||||
|  | ||||
|   hadjustment = st_scroll_bar_get_adjustment (ST_SCROLL_BAR(priv->hscroll)); | ||||
|   vadjustment = st_scroll_bar_get_adjustment (ST_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 | ||||
|         st_adjustment_set_value (vadjustment, value - step); | ||||
|       break; | ||||
|     case CLUTTER_SCROLL_DOWN: | ||||
|       if (value == upper) | ||||
|         return FALSE; | ||||
|       else | ||||
|         st_adjustment_set_value (vadjustment, value + step); | ||||
|       break; | ||||
|     case CLUTTER_SCROLL_LEFT: | ||||
|       if (value == lower) | ||||
|         return FALSE; | ||||
|       else | ||||
|         st_adjustment_set_value (hadjustment, value - step); | ||||
|       break; | ||||
|     case CLUTTER_SCROLL_RIGHT: | ||||
|       if (value == upper) | ||||
|         return FALSE; | ||||
|       else | ||||
|         st_adjustment_set_value (hadjustment, value + step); | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_scroll_view_class_init (StScrollViewClass *klass) | ||||
| { | ||||
|   GParamSpec *pspec; | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   StWidgetClass *widget_class = ST_WIDGET_CLASS (klass); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (StScrollViewPrivate)); | ||||
|  | ||||
|   object_class->get_property = st_scroll_view_get_property; | ||||
|   object_class->set_property = st_scroll_view_set_property; | ||||
|   object_class->dispose= st_scroll_view_dispose; | ||||
|   object_class->finalize = st_scroll_view_finalize; | ||||
|  | ||||
|   actor_class->paint = st_scroll_view_paint; | ||||
|   actor_class->pick = st_scroll_view_pick; | ||||
|   actor_class->get_preferred_width = st_scroll_view_get_preferred_width; | ||||
|   actor_class->get_preferred_height = st_scroll_view_get_preferred_height; | ||||
|   actor_class->allocate = st_scroll_view_allocate; | ||||
|   actor_class->scroll_event = st_scroll_view_scroll_event; | ||||
|  | ||||
|   widget_class->style_changed = st_scroll_view_style_changed; | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_HSCROLL, | ||||
|                                    g_param_spec_object ("hscroll", | ||||
|                                                         "StScrollBar", | ||||
|                                                         "Horizontal scroll indicator", | ||||
|                                                         ST_TYPE_SCROLL_BAR, | ||||
|                                                         G_PARAM_READABLE)); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_VSCROLL, | ||||
|                                    g_param_spec_object ("vscroll", | ||||
|                                                         "StScrollBar", | ||||
|                                                         "Vertical scroll indicator", | ||||
|                                                         ST_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 (StAdjustment *adjustment, | ||||
|                              ClutterActor *bar) | ||||
| { | ||||
|   StScrollView *scroll; | ||||
|   gdouble lower, upper, page_size; | ||||
|  | ||||
|   scroll = ST_SCROLL_VIEW (clutter_actor_get_parent (bar)); | ||||
|  | ||||
|   /* Determine if this scroll-bar should be visible */ | ||||
|   st_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) | ||||
| { | ||||
|   StAdjustment *hadjust; | ||||
|  | ||||
|   ClutterActor *actor = CLUTTER_ACTOR (gobject); | ||||
|   StScrollViewPrivate *priv = ST_SCROLL_VIEW (user_data)->priv; | ||||
|  | ||||
|   hadjust = st_scroll_bar_get_adjustment (ST_SCROLL_BAR(priv->hscroll)); | ||||
|   if (hadjust) | ||||
|     g_signal_handlers_disconnect_by_func (hadjust, | ||||
|                                           child_adjustment_changed_cb, | ||||
|                                           priv->hscroll); | ||||
|  | ||||
|   st_scrollable_get_adjustments (ST_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); | ||||
|         } | ||||
|  | ||||
|       st_scroll_bar_set_adjustment (ST_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) | ||||
| { | ||||
|   StAdjustment *vadjust; | ||||
|  | ||||
|   ClutterActor *actor = CLUTTER_ACTOR (gobject); | ||||
|   StScrollViewPrivate *priv = ST_SCROLL_VIEW (user_data)->priv; | ||||
|  | ||||
|   vadjust = st_scroll_bar_get_adjustment (ST_SCROLL_BAR(priv->vscroll)); | ||||
|   if (vadjust) | ||||
|     g_signal_handlers_disconnect_by_func (vadjust, | ||||
|                                           child_adjustment_changed_cb, | ||||
|                                           priv->vscroll); | ||||
|  | ||||
|   st_scrollable_get_adjustments (ST_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); | ||||
|         } | ||||
|  | ||||
|       st_scroll_bar_set_adjustment (ST_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 | ||||
| st_scroll_view_init (StScrollView *self) | ||||
| { | ||||
|   StScrollViewPrivate *priv = self->priv = SCROLL_VIEW_PRIVATE (self); | ||||
|  | ||||
|   priv->hscroll = CLUTTER_ACTOR (st_scroll_bar_new (NULL)); | ||||
|   priv->vscroll = g_object_new (ST_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 | ||||
| st_scroll_view_add (ClutterContainer *container, | ||||
|                     ClutterActor     *actor) | ||||
| { | ||||
|   StScrollView *self = ST_SCROLL_VIEW (container); | ||||
|   StScrollViewPrivate *priv = self->priv; | ||||
|  | ||||
|   if (ST_IS_SCROLLABLE (actor)) | ||||
|     { | ||||
|       priv->child = actor; | ||||
|  | ||||
|       /* chain up to StBin::add() */ | ||||
|       st_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 StScrollView, but the actor does " | ||||
|                  "not implement StScrollable.", | ||||
|                  g_type_name (G_OBJECT_TYPE (actor))); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_scroll_view_remove (ClutterContainer *container, | ||||
|                        ClutterActor     *actor) | ||||
| { | ||||
|   StScrollViewPrivate *priv = ST_SCROLL_VIEW (container)->priv; | ||||
|  | ||||
|   if (actor == priv->child) | ||||
|     { | ||||
|       g_object_ref (priv->child); | ||||
|  | ||||
|       /* chain up to StBin::remove() */ | ||||
|       st_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); | ||||
|       st_scrollable_set_adjustments ((StScrollable*) priv->child, NULL, NULL); | ||||
|  | ||||
|       g_object_unref (priv->child); | ||||
|       priv->child = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_scroll_view_foreach_with_internals (ClutterContainer *container, | ||||
|                                        ClutterCallback   callback, | ||||
|                                        gpointer          user_data) | ||||
| { | ||||
|   StScrollViewPrivate *priv = ST_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 StBin implementation of | ||||
|    * ClutterContainer so that we can chain up when | ||||
|    * overriding the methods | ||||
|    */ | ||||
|   st_scroll_view_parent_iface = g_type_interface_peek_parent (iface); | ||||
|  | ||||
|   iface->add = st_scroll_view_add; | ||||
|   iface->remove = st_scroll_view_remove; | ||||
|   iface->foreach_with_internals = st_scroll_view_foreach_with_internals; | ||||
| } | ||||
|  | ||||
| StWidget * | ||||
| st_scroll_view_new (void) | ||||
| { | ||||
|   return g_object_new (ST_TYPE_SCROLL_VIEW, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_scroll_view_get_hscroll_bar: | ||||
|  * @scroll: a #StScrollView | ||||
|  * | ||||
|  * Gets the horizontal scrollbar of the scrollbiew | ||||
|  * | ||||
|  * Return value: (transfer none): the horizontal #StScrollbar | ||||
|  */ | ||||
| ClutterActor * | ||||
| st_scroll_view_get_hscroll_bar (StScrollView *scroll) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_SCROLL_VIEW (scroll), NULL); | ||||
|  | ||||
|   return scroll->priv->hscroll; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_scroll_view_get_vscroll_bar: | ||||
|  * @scroll: a #StScrollView | ||||
|  * | ||||
|  * Gets the vertical scrollbar of the scrollbiew | ||||
|  * | ||||
|  * Return value: (transfer none): the vertical #StScrollbar | ||||
|  */ | ||||
| ClutterActor * | ||||
| st_scroll_view_get_vscroll_bar (StScrollView *scroll) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_SCROLL_VIEW (scroll), NULL); | ||||
|  | ||||
|   return scroll->priv->vscroll; | ||||
| } | ||||
|  | ||||
| gfloat | ||||
| st_scroll_view_get_column_size (StScrollView *scroll) | ||||
| { | ||||
|   StAdjustment *adjustment; | ||||
|   gdouble column_size; | ||||
|  | ||||
|   g_return_val_if_fail (scroll, 0); | ||||
|  | ||||
|   adjustment = st_scroll_bar_get_adjustment ( | ||||
|     ST_SCROLL_BAR (scroll->priv->hscroll)); | ||||
|   g_object_get (adjustment, | ||||
|                 "step-increment", &column_size, | ||||
|                 NULL); | ||||
|  | ||||
|   return column_size; | ||||
| } | ||||
|  | ||||
| void | ||||
| st_scroll_view_set_column_size (StScrollView *scroll, | ||||
|                                 gfloat        column_size) | ||||
| { | ||||
|   StAdjustment *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 = st_scroll_bar_get_adjustment ( | ||||
|         ST_SCROLL_BAR (scroll->priv->hscroll)); | ||||
|  | ||||
|       if (adjustment) | ||||
|         g_object_set (adjustment, | ||||
|                       "step-increment", (gdouble) scroll->priv->column_size, | ||||
|                       NULL); | ||||
|     } | ||||
| } | ||||
|  | ||||
| gfloat | ||||
| st_scroll_view_get_row_size (StScrollView *scroll) | ||||
| { | ||||
|   StAdjustment *adjustment; | ||||
|   gdouble row_size; | ||||
|  | ||||
|   g_return_val_if_fail (scroll, 0); | ||||
|  | ||||
|   adjustment = st_scroll_bar_get_adjustment ( | ||||
|     ST_SCROLL_BAR (scroll->priv->vscroll)); | ||||
|   g_object_get (adjustment, | ||||
|                 "step-increment", &row_size, | ||||
|                 NULL); | ||||
|  | ||||
|   return row_size; | ||||
| } | ||||
|  | ||||
| void | ||||
| st_scroll_view_set_row_size (StScrollView *scroll, | ||||
|                              gfloat        row_size) | ||||
| { | ||||
|   StAdjustment *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 = st_scroll_bar_get_adjustment ( | ||||
|         ST_SCROLL_BAR (scroll->priv->vscroll)); | ||||
|  | ||||
|       if (adjustment) | ||||
|         g_object_set (adjustment, | ||||
|                       "step-increment", (gdouble) scroll->priv->row_size, | ||||
|                       NULL); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| st_scroll_view_set_mouse_scrolling (StScrollView *scroll, | ||||
|                                     gboolean      enabled) | ||||
| { | ||||
|   StScrollViewPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_SCROLL_VIEW (scroll)); | ||||
|  | ||||
|   priv = ST_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 | ||||
| st_scroll_view_get_mouse_scrolling (StScrollView *scroll) | ||||
| { | ||||
|   StScrollViewPrivate *priv; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_SCROLL_VIEW (scroll), FALSE); | ||||
|  | ||||
|   priv = ST_SCROLL_VIEW (scroll)->priv; | ||||
|  | ||||
|   return priv->mouse_scroll; | ||||
| } | ||||
							
								
								
									
										89
									
								
								src/st/st-scroll-view.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/st/st-scroll-view.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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 St by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_SCROLL_VIEW_H__ | ||||
| #define __ST_SCROLL_VIEW_H__ | ||||
|  | ||||
| #include <st/st-bin.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_SCROLL_VIEW            (st_scroll_view_get_type()) | ||||
| #define ST_SCROLL_VIEW(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_SCROLL_VIEW, StScrollView)) | ||||
| #define ST_IS_SCROLL_VIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_SCROLL_VIEW)) | ||||
| #define ST_SCROLL_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_SCROLL_VIEW, StScrollViewClass)) | ||||
| #define ST_IS_SCROLL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_SCROLL_VIEW)) | ||||
| #define ST_SCROLL_VIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_SCROLL_VIEW, StScrollViewClass)) | ||||
|  | ||||
| typedef struct _StScrollView          StScrollView; | ||||
| typedef struct _StScrollViewPrivate   StScrollViewPrivate; | ||||
| typedef struct _StScrollViewClass     StScrollViewClass; | ||||
|  | ||||
| /** | ||||
|  * StScrollView: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _StScrollView | ||||
| { | ||||
|   /*< private >*/ | ||||
|   StBin parent_instance; | ||||
|  | ||||
|   StScrollViewPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _StScrollViewClass | ||||
| { | ||||
|   StBinClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType st_scroll_view_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| StWidget *st_scroll_view_new (void); | ||||
|  | ||||
| ClutterActor *st_scroll_view_get_hscroll_bar     (StScrollView *scroll); | ||||
| ClutterActor *st_scroll_view_get_vscroll_bar     (StScrollView *scroll); | ||||
|  | ||||
| gfloat        st_scroll_view_get_column_size     (StScrollView *scroll); | ||||
| void          st_scroll_view_set_column_size     (StScrollView *scroll, | ||||
|                                                   gfloat        column_size); | ||||
|  | ||||
| gfloat        st_scroll_view_get_row_size        (StScrollView *scroll); | ||||
| void          st_scroll_view_set_row_size        (StScrollView *scroll, | ||||
|                                                   gfloat        row_size); | ||||
|  | ||||
| void          st_scroll_view_set_mouse_scrolling (StScrollView *scroll, | ||||
|                                                   gboolean      enabled); | ||||
| gboolean      st_scroll_view_get_mouse_scrolling (StScrollView *scroll); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_SCROLL_VIEW_H__ */ | ||||
							
								
								
									
										97
									
								
								src/st/st-scrollable.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/st/st-scrollable.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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 St by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "st-scrollable.h" | ||||
|  | ||||
| static void | ||||
| st_scrollable_base_init (gpointer g_iface) | ||||
| { | ||||
|   static gboolean initialized = FALSE; | ||||
|  | ||||
|   if (!initialized) | ||||
|     { | ||||
|       g_object_interface_install_property (g_iface, | ||||
|                                            g_param_spec_object ("hadjustment", | ||||
|                                                                 "StAdjustment", | ||||
|                                                                 "Horizontal adjustment", | ||||
|                                                                 ST_TYPE_ADJUSTMENT, | ||||
|                                                                 G_PARAM_READWRITE)); | ||||
|  | ||||
|       g_object_interface_install_property (g_iface, | ||||
|                                            g_param_spec_object ("vadjustment", | ||||
|                                                                 "StAdjustment", | ||||
|                                                                 "Vertical adjustment", | ||||
|                                                                 ST_TYPE_ADJUSTMENT, | ||||
|                                                                 G_PARAM_READWRITE)); | ||||
|  | ||||
|       initialized = TRUE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| GType | ||||
| st_scrollable_get_type (void) | ||||
| { | ||||
|   static GType type = 0; | ||||
|   if (type == 0) | ||||
|     { | ||||
|       static const GTypeInfo info = | ||||
|       { | ||||
|         sizeof (StScrollableInterface), | ||||
|         st_scrollable_base_init,          /* base_init */ | ||||
|         NULL, | ||||
|       }; | ||||
|       type = g_type_register_static (G_TYPE_INTERFACE, | ||||
|                                      "StScrollable", &info, 0); | ||||
|     } | ||||
|   return type; | ||||
| } | ||||
|  | ||||
| void | ||||
| st_scrollable_set_adjustments (StScrollable *scrollable, | ||||
|                                StAdjustment *hadjustment, | ||||
|                                StAdjustment *vadjustment) | ||||
| { | ||||
|   ST_SCROLLABLE_GET_INTERFACE (scrollable)->set_adjustments (scrollable, | ||||
|                                                              hadjustment, | ||||
|                                                              vadjustment); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_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 | ||||
| st_scrollable_get_adjustments (StScrollable  *scrollable, | ||||
|                                StAdjustment **hadjustment, | ||||
|                                StAdjustment **vadjustment) | ||||
| { | ||||
|   ST_SCROLLABLE_GET_INTERFACE (scrollable)->get_adjustments (scrollable, | ||||
|                                                              hadjustment, | ||||
|                                                              vadjustment); | ||||
| } | ||||
							
								
								
									
										70
									
								
								src/st/st-scrollable.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/st/st-scrollable.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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 St by: Robert Staudinger <robsta@openedhand.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_SCROLLABLE_H__ | ||||
| #define __ST_SCROLLABLE_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <st/st-adjustment.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_SCROLLABLE                (st_scrollable_get_type ()) | ||||
| #define ST_SCROLLABLE(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_SCROLLABLE, StScrollable)) | ||||
| #define ST_IS_SCROLLABLE(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_SCROLLABLE)) | ||||
| #define ST_SCROLLABLE_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), ST_TYPE_SCROLLABLE, StScrollableInterface)) | ||||
|  | ||||
| typedef struct _StScrollable StScrollable; /* Dummy object */ | ||||
| typedef struct _StScrollableInterface StScrollableInterface; | ||||
|  | ||||
| struct _StScrollableInterface | ||||
| { | ||||
|   GTypeInterface parent; | ||||
|  | ||||
|   void (* set_adjustments) (StScrollable  *scrollable, | ||||
|                             StAdjustment  *hadjustment, | ||||
|                             StAdjustment  *vadjustment); | ||||
|   void (* get_adjustments) (StScrollable  *scrollable, | ||||
|                             StAdjustment **hadjustment, | ||||
|                             StAdjustment **vadjustment); | ||||
| }; | ||||
|  | ||||
| GType st_scrollable_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| void st_scrollable_set_adjustments (StScrollable  *scrollable, | ||||
|                                     StAdjustment  *hadjustment, | ||||
|                                     StAdjustment  *vadjustment); | ||||
| void st_scrollable_get_adjustments (StScrollable  *scrollable, | ||||
|                                     StAdjustment **hadjustment, | ||||
|                                     StAdjustment **vadjustment); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_SCROLLABLE_H__ */ | ||||
							
								
								
									
										576
									
								
								src/st/st-subtexture.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										576
									
								
								src/st/st-subtexture.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,576 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-subtexture.h: Class to wrap a texture and "subframe" it. | ||||
|  * based on | ||||
|  * st-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 "st-subtexture.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_PARENT_TEXTURE, | ||||
|  | ||||
|   PROP_TOP, | ||||
|   PROP_LEFT, | ||||
|   PROP_WIDTH, | ||||
|   PROP_HEIGHT | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (StSubtexture, st_subtexture, CLUTTER_TYPE_ACTOR); | ||||
|  | ||||
| #define ST_SUBTEXTURE_GET_PRIVATE(obj)     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_SUBTEXTURE, StSubtexturePrivate)) | ||||
|  | ||||
| struct _StSubtexturePrivate | ||||
| { | ||||
|   ClutterTexture *parent_texture; | ||||
|  | ||||
|   int             left; | ||||
|   int             top; | ||||
|   int             width; | ||||
|   int             height; | ||||
|  | ||||
|   CoglHandle      material; | ||||
| }; | ||||
|  | ||||
| static void | ||||
| st_subtexture_get_preferred_width (ClutterActor *self, | ||||
|                                    gfloat        for_height, | ||||
|                                    gfloat       *min_width_p, | ||||
|                                    gfloat       *natural_width_p) | ||||
| { | ||||
|   StSubtexturePrivate *priv = ST_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 | ||||
| st_subtexture_get_preferred_height (ClutterActor *self, | ||||
|                                     gfloat        for_width, | ||||
|                                     gfloat       *min_height_p, | ||||
|                                     gfloat       *natural_height_p) | ||||
| { | ||||
|   StSubtexturePrivate *priv = ST_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 | ||||
| st_subtexture_realize (ClutterActor *self) | ||||
| { | ||||
|   StSubtexturePrivate *priv = ST_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 | ||||
| st_subtexture_unrealize (ClutterActor *self) | ||||
| { | ||||
|   StSubtexturePrivate *priv = ST_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 | ||||
| st_subtexture_paint (ClutterActor *self) | ||||
| { | ||||
|   StSubtexturePrivate *priv = ST_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 | ||||
| st_subtexture_set_frame_internal (StSubtexture *frame, | ||||
|                                   int           left, | ||||
|                                   int           top, | ||||
|                                   int           width, | ||||
|                                   int           height) | ||||
| { | ||||
|   StSubtexturePrivate *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 | ||||
| st_subtexture_set_property (GObject      *gobject, | ||||
|                             guint         prop_id, | ||||
|                             const GValue *value, | ||||
|                             GParamSpec   *pspec) | ||||
| { | ||||
|   StSubtexture *frame = ST_SUBTEXTURE (gobject); | ||||
|   StSubtexturePrivate *priv = frame->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_PARENT_TEXTURE: | ||||
|       st_subtexture_set_parent_texture (frame, | ||||
|                                         g_value_get_object (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TOP: | ||||
|       st_subtexture_set_frame_internal (frame, | ||||
|                                         priv->left, | ||||
|                                         g_value_get_int (value), | ||||
|                                         priv->width, | ||||
|                                         priv->height); | ||||
|       break; | ||||
|  | ||||
|     case PROP_LEFT: | ||||
|       st_subtexture_set_frame_internal (frame, | ||||
|                                         g_value_get_int (value), | ||||
|                                         priv->top, | ||||
|                                         priv->width, | ||||
|                                         priv->height); | ||||
|       break; | ||||
|  | ||||
|     case PROP_WIDTH: | ||||
|       st_subtexture_set_frame_internal (frame, | ||||
|                                         priv->left, | ||||
|                                         priv->top, | ||||
|                                         g_value_get_int (value), | ||||
|                                         priv->height); | ||||
|       break; | ||||
|  | ||||
|     case PROP_HEIGHT: | ||||
|       st_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 | ||||
| st_subtexture_get_property (GObject    *gobject, | ||||
|                             guint       prop_id, | ||||
|                             GValue     *value, | ||||
|                             GParamSpec *pspec) | ||||
| { | ||||
|   StSubtexturePrivate *priv = ST_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 | ||||
| st_subtexture_dispose (GObject *gobject) | ||||
| { | ||||
|   StSubtexturePrivate *priv = ST_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 (st_subtexture_parent_class)->dispose (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_subtexture_class_init (StSubtextureClass *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 (StSubtexturePrivate)); | ||||
|  | ||||
|   actor_class->get_preferred_width = | ||||
|     st_subtexture_get_preferred_width; | ||||
|   actor_class->get_preferred_height = | ||||
|     st_subtexture_get_preferred_height; | ||||
|   actor_class->realize = st_subtexture_realize; | ||||
|   actor_class->unrealize = st_subtexture_unrealize; | ||||
|   actor_class->paint = st_subtexture_paint; | ||||
|  | ||||
|   gobject_class->set_property = st_subtexture_set_property; | ||||
|   gobject_class->get_property = st_subtexture_get_property; | ||||
|   gobject_class->dispose = st_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 | ||||
| st_subtexture_init (StSubtexture *self) | ||||
| { | ||||
|   StSubtexturePrivate *priv; | ||||
|  | ||||
|   self->priv = priv = ST_SUBTEXTURE_GET_PRIVATE (self); | ||||
|  | ||||
|   priv->material = COGL_INVALID_HANDLE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_subtexture_new: | ||||
|  * @texture: a #ClutterTexture or %NULL | ||||
|  * @left: left | ||||
|  * @top: top | ||||
|  * @width: width | ||||
|  * @height: height | ||||
|  * | ||||
|  * A #StSubtexture is a specialized texture that efficiently clones | ||||
|  * an area of the given @texture while keeping preserving portions of the | ||||
|  * same texture. | ||||
|  * | ||||
|  * A #StSubtexture can be used to make a rectangular texture fit a | ||||
|  * given size without stretching its borders. | ||||
|  * | ||||
|  * Return value: the newly created #StSubtexture | ||||
|  */ | ||||
| ClutterActor* | ||||
| st_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 (ST_TYPE_SUBTEXTURE, | ||||
|                        "parent-texture", texture, | ||||
|                        "top", top, | ||||
|                        "left", left, | ||||
|                        "width", width, | ||||
|                        "height", height, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_subtexture_get_parent_texture: | ||||
|  * @frame: A #StSubtexture | ||||
|  * | ||||
|  * Return the texture used by the #StSubtexture | ||||
|  * | ||||
|  * Returns: (transfer none): a #ClutterTexture owned by the #StSubtexture | ||||
|  */ | ||||
| ClutterTexture * | ||||
| st_subtexture_get_parent_texture (StSubtexture *frame) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_SUBTEXTURE (frame), NULL); | ||||
|  | ||||
|   return frame->priv->parent_texture; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_subtexture_set_parent_texture: | ||||
|  * @frame: A #StSubtexture | ||||
|  * @texture: A #ClutterTexture | ||||
|  * | ||||
|  * Set the #ClutterTexture used by this #StSubtexture | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_subtexture_set_parent_texture (StSubtexture   *frame, | ||||
|                                   ClutterTexture *texture) | ||||
| { | ||||
|   StSubtexturePrivate *priv; | ||||
|   gboolean was_visible; | ||||
|  | ||||
|   g_return_if_fail (ST_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"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_subtexture_set_frame: | ||||
|  * @frame: A #StSubtexture | ||||
|  * @left: left | ||||
|  * @top: top | ||||
|  * @width: width | ||||
|  * @height: height | ||||
|  * | ||||
|  * Set the frame of the subtexture | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_subtexture_set_frame (StSubtexture *frame, | ||||
|                          gint          left, | ||||
|                          gint          top, | ||||
|                          gint          width, | ||||
|                          gint          height) | ||||
| { | ||||
|   g_return_if_fail (ST_IS_SUBTEXTURE (frame)); | ||||
|  | ||||
|   st_subtexture_set_frame_internal (frame, left, top, width, height); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_subtexture_get_frame: | ||||
|  * @frame: A #StSubtexture | ||||
|  * @left: left | ||||
|  * @top: top | ||||
|  * @width: width | ||||
|  * @height: height | ||||
|  * | ||||
|  * Retrieve the current frame. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_subtexture_get_frame (StSubtexture *frame, | ||||
|                          gint         *left, | ||||
|                          gint         *top, | ||||
|                          gint         *width, | ||||
|                          gint         *height) | ||||
| { | ||||
|   StSubtexturePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_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; | ||||
| } | ||||
							
								
								
									
										97
									
								
								src/st/st-subtexture.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/st/st-subtexture.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-subtexture.h: Class to wrap a texture and "subframe" it. | ||||
|  * | ||||
|  * Based on | ||||
|  * st-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(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_SUBTEXTURE_H__ | ||||
| #define __ST_SUBTEXTURE_H__ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_SUBTEXTURE                 (st_subtexture_get_type ()) | ||||
| #define ST_SUBTEXTURE(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_SUBTEXTURE, StSubtexture)) | ||||
| #define ST_SUBTEXTURE_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_SUBTEXTURE, StSubtextureClass)) | ||||
| #define ST_IS_SUBTEXTURE(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_SUBTEXTURE)) | ||||
| #define ST_IS_SUBTEXTURE_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_SUBTEXTURE)) | ||||
| #define ST_SUBTEXTURE_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_SUBTEXTURE, StSubtextureClass)) | ||||
|  | ||||
| typedef struct _StSubtexture                StSubtexture; | ||||
| typedef struct _StSubtexturePrivate         StSubtexturePrivate; | ||||
| typedef struct _StSubtextureClass           StSubtextureClass; | ||||
|  | ||||
| /** | ||||
|  * StSubtexture: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _StSubtexture | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActor parent_instance; | ||||
|    | ||||
|   StSubtexturePrivate    *priv; | ||||
| }; | ||||
|  | ||||
| struct _StSubtextureClass  | ||||
| { | ||||
|   ClutterActorClass parent_class; | ||||
|  | ||||
|   /* padding for future expansion */ | ||||
|   void (*_st_box_1) (void); | ||||
|   void (*_st_box_2) (void); | ||||
|   void (*_st_box_3) (void); | ||||
|   void (*_st_box_4) (void); | ||||
| };  | ||||
|  | ||||
| GType st_subtexture_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| ClutterActor *  st_subtexture_new                (ClutterTexture *texture, | ||||
|                                                   gint            top, | ||||
|                                                   gint            left, | ||||
|                                                   gint            width, | ||||
|                                                   gint            height); | ||||
| void            st_subtexture_set_parent_texture (StSubtexture   *frame, | ||||
|                                                   ClutterTexture *texture); | ||||
| ClutterTexture *st_subtexture_get_parent_texture (StSubtexture   *frame); | ||||
| void            st_subtexture_set_frame          (StSubtexture   *frame, | ||||
|                                                   gint            top, | ||||
|                                                   gint            left, | ||||
|                                                   gint            width, | ||||
|                                                   gint            height); | ||||
| void            st_subtexture_get_frame          (StSubtexture   *frame, | ||||
|                                                   gint           *top, | ||||
|                                                   gint           *left, | ||||
|                                                   gint           *width, | ||||
|                                                   gint           *height); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_SUBTEXTURE_H__ */ | ||||
							
								
								
									
										805
									
								
								src/st/st-table-child.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										805
									
								
								src/st/st-table-child.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,805 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-table-child.h: Table child implementation | ||||
|  * | ||||
|  * 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.wood@intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "st-private.h" | ||||
| #include "st-table-child.h" | ||||
| #include "st-table-private.h" | ||||
| #include <st/st-widget.h> | ||||
| #include <st/st-table.h> | ||||
|  | ||||
| /* | ||||
|  * ClutterChildMeta Implementation | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:st-table-child | ||||
|  * @short_description: The child property store for #StTable | ||||
|  * | ||||
|  * The #ClutterChildMeta implementation for the #StTable container widget. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| enum { | ||||
|   CHILD_PROP_0, | ||||
|  | ||||
|   CHILD_PROP_COL, | ||||
|   CHILD_PROP_ROW, | ||||
|   CHILD_PROP_COL_SPAN, | ||||
|   CHILD_PROP_ROW_SPAN, | ||||
|   CHILD_PROP_X_EXPAND, | ||||
|   CHILD_PROP_Y_EXPAND, | ||||
|   CHILD_PROP_X_ALIGN, | ||||
|   CHILD_PROP_Y_ALIGN, | ||||
|   CHILD_PROP_X_FILL, | ||||
|   CHILD_PROP_Y_FILL, | ||||
|   CHILD_PROP_ALLOCATE_HIDDEN, | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (StTableChild, st_table_child, CLUTTER_TYPE_CHILD_META); | ||||
|  | ||||
| static void | ||||
| table_child_set_property (GObject      *gobject, | ||||
|                           guint         prop_id, | ||||
|                           const GValue *value, | ||||
|                           GParamSpec   *pspec) | ||||
| { | ||||
|   StTableChild *child = ST_TABLE_CHILD (gobject); | ||||
|   StTable *table = ST_TABLE (CLUTTER_CHILD_META(gobject)->container); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case CHILD_PROP_COL: | ||||
|       child->col = g_value_get_int (value); | ||||
|       _st_table_update_row_col (table, -1, child->col); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (table)); | ||||
|       break; | ||||
|     case CHILD_PROP_ROW: | ||||
|       child->row = g_value_get_int (value); | ||||
|       _st_table_update_row_col (table, child->row, -1); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (table)); | ||||
|       break; | ||||
|     case CHILD_PROP_COL_SPAN: | ||||
|       child->col_span = g_value_get_int (value); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (table)); | ||||
|       break; | ||||
|     case CHILD_PROP_ROW_SPAN: | ||||
|       child->row_span = g_value_get_int (value); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (table)); | ||||
|       break; | ||||
|     case CHILD_PROP_X_EXPAND: | ||||
|       child->x_expand = g_value_get_boolean (value); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (table)); | ||||
|       break; | ||||
|     case CHILD_PROP_Y_EXPAND: | ||||
|       child->y_expand = g_value_get_boolean (value); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (table)); | ||||
|       break; | ||||
|     case CHILD_PROP_X_ALIGN: | ||||
|       child->x_align = g_value_get_double (value); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (table)); | ||||
|       break; | ||||
|     case CHILD_PROP_Y_ALIGN: | ||||
|       child->y_align = g_value_get_double (value); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (table)); | ||||
|       break; | ||||
|     case CHILD_PROP_X_FILL: | ||||
|       child->x_fill = g_value_get_boolean (value); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (table)); | ||||
|       break; | ||||
|     case CHILD_PROP_Y_FILL: | ||||
|       child->y_fill = g_value_get_boolean (value); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (table)); | ||||
|       break; | ||||
|     case CHILD_PROP_ALLOCATE_HIDDEN: | ||||
|       child->allocate_hidden = g_value_get_boolean (value); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (table)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| table_child_get_property (GObject    *gobject, | ||||
|                           guint       prop_id, | ||||
|                           GValue     *value, | ||||
|                           GParamSpec *pspec) | ||||
| { | ||||
|   StTableChild *child = ST_TABLE_CHILD (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case CHILD_PROP_COL: | ||||
|       g_value_set_int (value, child->col); | ||||
|       break; | ||||
|     case CHILD_PROP_ROW: | ||||
|       g_value_set_int (value, child->row); | ||||
|       break; | ||||
|     case CHILD_PROP_COL_SPAN: | ||||
|       g_value_set_int (value, child->col_span); | ||||
|       break; | ||||
|     case CHILD_PROP_ROW_SPAN: | ||||
|       g_value_set_int (value, child->row_span); | ||||
|       break; | ||||
|     case CHILD_PROP_X_EXPAND: | ||||
|       g_value_set_boolean (value, child->x_expand); | ||||
|       break; | ||||
|     case CHILD_PROP_Y_EXPAND: | ||||
|       g_value_set_boolean (value, child->y_expand); | ||||
|       break; | ||||
|     case CHILD_PROP_X_ALIGN: | ||||
|       g_value_set_double (value, child->x_align); | ||||
|       break; | ||||
|     case CHILD_PROP_Y_ALIGN: | ||||
|       g_value_set_double (value, child->y_align); | ||||
|       break; | ||||
|     case CHILD_PROP_X_FILL: | ||||
|       g_value_set_boolean (value, child->x_fill); | ||||
|       break; | ||||
|     case CHILD_PROP_Y_FILL: | ||||
|       g_value_set_boolean (value, child->y_fill); | ||||
|       break; | ||||
|     case CHILD_PROP_ALLOCATE_HIDDEN: | ||||
|       g_value_set_boolean (value, child->allocate_hidden); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_table_child_class_init (StTableChildClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   gobject_class->set_property = table_child_set_property; | ||||
|   gobject_class->get_property = table_child_get_property; | ||||
|  | ||||
|   pspec = g_param_spec_int ("col", | ||||
|                             "Column Number", | ||||
|                             "The column the widget resides in", | ||||
|                             0, G_MAXINT, | ||||
|                             0, | ||||
|                             ST_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, CHILD_PROP_COL, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_int ("row", | ||||
|                             "Row Number", | ||||
|                             "The row the widget resides in", | ||||
|                             0, G_MAXINT, | ||||
|                             0, | ||||
|                             ST_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, CHILD_PROP_ROW, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_int ("row-span", | ||||
|                             "Row Span", | ||||
|                             "The number of rows the widget should span", | ||||
|                             1, G_MAXINT, | ||||
|                             1, | ||||
|                             ST_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, CHILD_PROP_ROW_SPAN, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_int ("col-span", | ||||
|                             "Column Span", | ||||
|                             "The number of columns the widget should span", | ||||
|                             1, G_MAXINT, | ||||
|                             1, | ||||
|                             ST_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, CHILD_PROP_COL_SPAN, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("x-expand", | ||||
|                                 "X Expand", | ||||
|                                 "Whether the child should receive priority " | ||||
|                                 "when the container is allocating spare space " | ||||
|                                 "on the horizontal axis", | ||||
|                                 TRUE, | ||||
|                                 ST_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, CHILD_PROP_X_EXPAND, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("y-expand", | ||||
|                                 "Y Expand", | ||||
|                                 "Whether the child should receive priority " | ||||
|                                 "when the container is allocating spare space " | ||||
|                                 "on the vertical axis", | ||||
|                                 TRUE, | ||||
|                                 ST_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, CHILD_PROP_Y_EXPAND, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_double ("x-align", | ||||
|                                "X Alignment", | ||||
|                                "X alignment of the widget within the cell", | ||||
|                                0, 1, | ||||
|                                0.5, | ||||
|                                ST_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, CHILD_PROP_X_ALIGN, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_double ("y-align", | ||||
|                                "Y Alignment", | ||||
|                                "Y alignment of the widget within the cell", | ||||
|                                0, 1, | ||||
|                                0.5, | ||||
|                                ST_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, CHILD_PROP_Y_ALIGN, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("x-fill", | ||||
|                                 "X Fill", | ||||
|                                 "Whether the child should be allocated its " | ||||
|                                 "entire available space, or whether it should " | ||||
|                                 "be squashed and aligned.", | ||||
|                                 TRUE, | ||||
|                                 ST_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, CHILD_PROP_X_FILL, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("y-fill", | ||||
|                                 "Y Fill", | ||||
|                                 "Whether the child should be allocated its " | ||||
|                                 "entire available space, or whether it should " | ||||
|                                 "be squashed and aligned.", | ||||
|                                 TRUE, | ||||
|                                 ST_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, CHILD_PROP_Y_FILL, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_boolean ("allocate-hidden", | ||||
|                                 "Allocate Hidden", | ||||
|                                 "Whether the child should be allocate even " | ||||
|                                 "if it is hidden", | ||||
|                                 TRUE, | ||||
|                                 ST_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, CHILD_PROP_ALLOCATE_HIDDEN, pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_table_child_init (StTableChild *self) | ||||
| { | ||||
|   self->col_span = 1; | ||||
|   self->row_span = 1; | ||||
|  | ||||
|   self->x_align = 0.5; | ||||
|   self->y_align = 0.5; | ||||
|  | ||||
|   self->x_expand = TRUE; | ||||
|   self->y_expand = TRUE; | ||||
|  | ||||
|   self->x_fill = TRUE; | ||||
|   self->y_fill = TRUE; | ||||
|  | ||||
|   self->allocate_hidden = TRUE; | ||||
| } | ||||
|  | ||||
| static StTableChild* | ||||
| get_child_meta (StTable      *table, | ||||
|                 ClutterActor *child) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   meta = (StTableChild*) clutter_container_get_child_meta (CLUTTER_CONTAINER (table), child); | ||||
|  | ||||
|   return meta; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_get_col_span: | ||||
|  * @table: an #StTable | ||||
|  * @child: a #ClutterActor | ||||
|  * | ||||
|  * Get the column span of the child. Defaults to 1. | ||||
|  * | ||||
|  * Returns: the column span of the child | ||||
|  */ | ||||
| gint | ||||
| st_table_child_get_col_span (StTable      *table, | ||||
|                              ClutterActor *child) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_TABLE (table), 0); | ||||
|   g_return_val_if_fail (CLUTTER_IS_ACTOR (child), 0); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   return meta->col_span; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_set_col_span: | ||||
|  * @table: An #StTable | ||||
|  * @child: An #ClutterActor | ||||
|  * @span: The number of columns to span | ||||
|  * | ||||
|  * Set the column span of the child. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_table_child_set_col_span (StTable      *table, | ||||
|                              ClutterActor *child, | ||||
|                              gint          span) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_TABLE (table)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (child)); | ||||
|   g_return_if_fail (span > 1); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   meta->col_span = span; | ||||
|  | ||||
|   clutter_actor_queue_relayout (child); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_get_row_span: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * | ||||
|  * Get the row span of the child. Defaults to 1. | ||||
|  * | ||||
|  * Returns: the row span of the child | ||||
|  */ | ||||
| gint | ||||
| st_table_child_get_row_span (StTable      *table, | ||||
|                              ClutterActor *child) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_TABLE (table), 0); | ||||
|   g_return_val_if_fail (CLUTTER_IS_ACTOR (child), 0); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   return meta->row_span; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_set_row_span: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * @span: the number of rows to span | ||||
|  * | ||||
|  * Set the row span of the child. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_table_child_set_row_span (StTable      *table, | ||||
|                              ClutterActor *child, | ||||
|                              gint          span) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_TABLE (table)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (child)); | ||||
|   g_return_if_fail (span > 1); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   meta->row_span = span; | ||||
|  | ||||
|   clutter_actor_queue_relayout (child); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_get_x_fill: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * | ||||
|  * Get the x-fill state of the child | ||||
|  * | ||||
|  * Returns: #TRUE if the child is set to x-fill | ||||
|  */ | ||||
| gboolean | ||||
| st_table_child_get_x_fill (StTable      *table, | ||||
|                            ClutterActor *child) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_TABLE (table), 0); | ||||
|   g_return_val_if_fail (CLUTTER_IS_ACTOR (child), 0); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   return meta->x_fill; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_set_x_fill: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * @fill: the fill state | ||||
|  * | ||||
|  * Set the fill state of the child on the x-axis. This will cause the child to | ||||
|  * be allocated the maximum available space. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_table_child_set_x_fill (StTable      *table, | ||||
|                            ClutterActor *child, | ||||
|                            gboolean      fill) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_TABLE (table)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (child)); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   meta->x_fill = fill; | ||||
|  | ||||
|   clutter_actor_queue_relayout (child); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * st_table_child_get_y_fill: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * | ||||
|  * Get the y-fill state of the child | ||||
|  * | ||||
|  * Returns: #TRUE if the child is set to y-fill | ||||
|  */ | ||||
| gboolean | ||||
| st_table_child_get_y_fill (StTable      *table, | ||||
|                            ClutterActor *child) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_TABLE (table), 0); | ||||
|   g_return_val_if_fail (CLUTTER_IS_ACTOR (child), 0); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   return meta->y_fill; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_set_y_fill: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * @fill: the fill state | ||||
|  * | ||||
|  * Set the fill state of the child on the y-axis. This will cause the child to | ||||
|  * be allocated the maximum available space. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_table_child_set_y_fill (StTable      *table, | ||||
|                            ClutterActor *child, | ||||
|                            gboolean      fill) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_TABLE (table)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (child)); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   meta->y_fill = fill; | ||||
|  | ||||
|   clutter_actor_queue_relayout (child); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_get_x_expand: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * | ||||
|  * Get the x-expand property of the child | ||||
|  * | ||||
|  * Returns: #TRUE if the child is set to x-expand | ||||
|  */ | ||||
| gboolean | ||||
| st_table_child_get_x_expand (StTable      *table, | ||||
|                              ClutterActor *child) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_TABLE (table), 0); | ||||
|   g_return_val_if_fail (CLUTTER_IS_ACTOR (child), 0); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   return meta->x_expand; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_set_x_expand: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * @expand: the new value of the x expand child property | ||||
|  * | ||||
|  * Set x-expand on the child. This causes the column which the child | ||||
|  * resides in to be allocated any extra space if the allocation of the table is | ||||
|  * larger than the preferred size. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_table_child_set_x_expand (StTable      *table, | ||||
|                              ClutterActor *child, | ||||
|                              gboolean      expand) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_TABLE (table)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (child)); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   meta->x_expand = expand; | ||||
|  | ||||
|   clutter_actor_queue_relayout (child); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_set_y_expand: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * @expand: the new value of the y-expand child property | ||||
|  * | ||||
|  * Set y-expand on the child. This causes the row which the child | ||||
|  * resides in to be allocated any extra space if the allocation of the table is | ||||
|  * larger than the preferred size. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_table_child_set_y_expand (StTable      *table, | ||||
|                              ClutterActor *child, | ||||
|                              gboolean      expand) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_TABLE (table)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (child)); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   meta->y_expand = expand; | ||||
|  | ||||
|   clutter_actor_queue_relayout (child); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_get_y_expand: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * | ||||
|  * Get the y-expand property of the child. | ||||
|  * | ||||
|  * Returns: #TRUE if the child is set to y-expand | ||||
|  */ | ||||
| gboolean | ||||
| st_table_child_get_y_expand (StTable      *table, | ||||
|                              ClutterActor *child) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_TABLE (table), 0); | ||||
|   g_return_val_if_fail (CLUTTER_IS_ACTOR (child), 0); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   return meta->y_expand; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_get_x_align: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * | ||||
|  * Get the x-align value of the child | ||||
|  * | ||||
|  * Returns: An #StAlign value | ||||
|  */ | ||||
| StAlign | ||||
| st_table_child_get_x_align (StTable      *table, | ||||
|                             ClutterActor *child) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_TABLE (table), 0); | ||||
|   g_return_val_if_fail (CLUTTER_IS_ACTOR (child), 0); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   if (meta->x_align == 0.0) | ||||
|     return ST_ALIGN_START; | ||||
|   else if (meta->x_align == 1.0) | ||||
|     return ST_ALIGN_END; | ||||
|   else | ||||
|     return ST_ALIGN_MIDDLE; | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_set_x_align: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * @align: A #StAlign value | ||||
|  * | ||||
|  * Set the alignment of the child within its cell. This will only have an effect | ||||
|  * if the the x-fill property is FALSE. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_table_child_set_x_align (StTable      *table, | ||||
|                             ClutterActor *child, | ||||
|                             StAlign       align) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_TABLE (table)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (child)); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   switch (align) | ||||
|     { | ||||
|     case ST_ALIGN_START: | ||||
|       meta->x_align = 0.0; | ||||
|       break; | ||||
|     case ST_ALIGN_MIDDLE: | ||||
|       meta->x_align = 0.5; | ||||
|       break; | ||||
|     case ST_ALIGN_END: | ||||
|       meta->x_align = 1.0; | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_relayout (child); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_get_y_align: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * | ||||
|  * Get the y-align value of the child | ||||
|  * | ||||
|  * Returns: An #StAlign value | ||||
|  */ | ||||
| StAlign | ||||
| st_table_child_get_y_align (StTable      *table, | ||||
|                             ClutterActor *child) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_TABLE (table), 0); | ||||
|   g_return_val_if_fail (CLUTTER_IS_ACTOR (child), 0); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   if (meta->y_align == 0.0) | ||||
|     return ST_ALIGN_START; | ||||
|   else if (meta->y_align == 1.0) | ||||
|     return ST_ALIGN_END; | ||||
|   else | ||||
|     return ST_ALIGN_MIDDLE; | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_set_y_align: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * @align: A #StAlign value | ||||
|  * | ||||
|  * Set the value of the y-align property. This will only have an effect if | ||||
|  * y-fill value is set to FALSE. | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_table_child_set_y_align (StTable      *table, | ||||
|                             ClutterActor *child, | ||||
|                             StAlign       align) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_TABLE (table)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (child)); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   switch (align) | ||||
|     { | ||||
|     case ST_ALIGN_START: | ||||
|       meta->y_align = 0.0; | ||||
|       break; | ||||
|     case ST_ALIGN_MIDDLE: | ||||
|       meta->y_align = 0.5; | ||||
|       break; | ||||
|     case ST_ALIGN_END: | ||||
|       meta->y_align = 1.0; | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_relayout (child); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_set_allocate_hidden: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * @value: #TRUE if the actor should be allocated when hidden | ||||
|  * | ||||
|  * Set whether the child should be allocate even if it is hidden | ||||
|  */ | ||||
| void | ||||
| st_table_child_set_allocate_hidden (StTable      *table, | ||||
|                                     ClutterActor *child, | ||||
|                                     gboolean      value) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_TABLE (table)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (child)); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   if (meta->allocate_hidden != value) | ||||
|     { | ||||
|       meta->allocate_hidden = value; | ||||
|  | ||||
|       clutter_actor_queue_relayout (child); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (meta), "allocate-hidden"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_table_child_get_allocate_hidden: | ||||
|  * @table: A #StTable | ||||
|  * @child: A #ClutterActor | ||||
|  * | ||||
|  * Determine if the child is allocated even if it is hidden | ||||
|  * | ||||
|  * Returns: #TRUE if the actor is allocated when hidden | ||||
|  */ | ||||
| gboolean | ||||
| st_table_child_get_allocate_hidden (StTable      *table, | ||||
|                                     ClutterActor *child) | ||||
| { | ||||
|   StTableChild *meta; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_TABLE (table), TRUE); | ||||
|   g_return_val_if_fail (CLUTTER_IS_ACTOR (child), TRUE); | ||||
|  | ||||
|   meta = get_child_meta (table, child); | ||||
|  | ||||
|   return meta->allocate_hidden; | ||||
| } | ||||
							
								
								
									
										129
									
								
								src/st/st-table-child.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								src/st/st-table-child.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-table-child.h: Table child implementation | ||||
|  * | ||||
|  * 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(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_TABLE_CHILD_H__ | ||||
| #define __ST_TABLE_CHILD_H__ | ||||
|  | ||||
| #include <st/st-types.h> | ||||
| #include <st/st-widget.h> | ||||
| #include <st/st-table.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_TABLE_CHILD          (st_table_child_get_type ()) | ||||
| #define ST_TABLE_CHILD(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_TABLE_CHILD, StTableChild)) | ||||
| #define ST_IS_TABLE_CHILD(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_TABLE_CHILD)) | ||||
| #define ST_TABLE_CHILD_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_TABLE_CHILD, StTableChildClass)) | ||||
| #define ST_IS_TABLE_CHILD_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_TABLE_CHILD)) | ||||
| #define ST_TABLE_CHILD_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_TABLE_CHILD, StTableChildClass)) | ||||
|  | ||||
| typedef struct _StTableChild         StTableChild; | ||||
| typedef struct _StTableChildClass    StTableChildClass; | ||||
|  | ||||
| /** | ||||
|  * StTableChild: | ||||
|  * | ||||
|  * The contents of the this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _StTableChild | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterChildMeta parent_instance; | ||||
|  | ||||
|   gint col; | ||||
|   gint row; | ||||
|   gint col_span; | ||||
|   gint row_span; | ||||
|   gdouble x_align; | ||||
|   gdouble y_align; | ||||
|   guint allocate_hidden : 1; | ||||
|   guint x_expand : 1; | ||||
|   guint y_expand : 1; | ||||
|   guint x_fill : 1; | ||||
|   guint y_fill : 1; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct _StTableChildClass | ||||
| { | ||||
|   ClutterChildMetaClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType st_table_child_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| gint     st_table_child_get_col_span        (StTable      *table, | ||||
|                                              ClutterActor *child); | ||||
| void     st_table_child_set_col_span        (StTable      *table, | ||||
|                                              ClutterActor *child, | ||||
|                                              gint          span); | ||||
| gint     st_table_child_get_row_span        (StTable      *table, | ||||
|                                              ClutterActor *child); | ||||
| void     st_table_child_set_row_span        (StTable      *table, | ||||
|                                              ClutterActor *child, | ||||
|                                              gint          span); | ||||
| gboolean st_table_child_get_x_fill          (StTable      *table, | ||||
|                                              ClutterActor *child); | ||||
| void     st_table_child_set_x_fill          (StTable      *table, | ||||
|                                              ClutterActor *child, | ||||
|                                              gboolean      fill); | ||||
| gboolean st_table_child_get_y_fill          (StTable      *table, | ||||
|                                              ClutterActor *child); | ||||
| void     st_table_child_set_y_fill          (StTable      *table, | ||||
|                                              ClutterActor *child, | ||||
|                                              gboolean      fill); | ||||
| gboolean st_table_child_get_x_expand        (StTable      *table, | ||||
|                                              ClutterActor *child); | ||||
| void     st_table_child_set_x_expand        (StTable      *table, | ||||
|                                              ClutterActor *child, | ||||
|                                              gboolean      expand); | ||||
| gboolean st_table_child_get_y_expand        (StTable      *table, | ||||
|                                              ClutterActor *child); | ||||
| void     st_table_child_set_y_expand        (StTable      *table, | ||||
|                                              ClutterActor *child, | ||||
|                                              gboolean      expand); | ||||
| StAlign  st_table_child_get_x_align         (StTable      *table, | ||||
|                                              ClutterActor *child); | ||||
| void     st_table_child_set_x_align         (StTable      *table, | ||||
|                                              ClutterActor *child, | ||||
|                                              StAlign       align); | ||||
| StAlign  st_table_child_get_y_align         (StTable      *table, | ||||
|                                              ClutterActor *child); | ||||
| void     st_table_child_set_y_align         (StTable      *table, | ||||
|                                              ClutterActor *child, | ||||
|                                              StAlign       align); | ||||
| void     st_table_child_set_allocate_hidden (StTable      *table, | ||||
|                                              ClutterActor *child, | ||||
|                                              gboolean      value); | ||||
| gboolean st_table_child_get_allocate_hidden (StTable      *table, | ||||
|                                              ClutterActor *child); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_TABLE_H__ */ | ||||
							
								
								
									
										36
									
								
								src/st/st-table-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/st/st-table-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| /* | ||||
|  * st-private-private.h: Private declarations for StTable | ||||
|  * | ||||
|  * 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 __ST_TABLE_PRIVATE_H__ | ||||
| #define __ST_TABLE_PRIVATE_H__ | ||||
|  | ||||
| #include "st-table.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| void _st_table_update_row_col (StTable *table, | ||||
| 			       gint     row, | ||||
| 			       gint     col); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_TABLE_PRIVATE_H__ */ | ||||
							
								
								
									
										1257
									
								
								src/st/st-table.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1257
									
								
								src/st/st-table.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										95
									
								
								src/st/st-table.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/st/st-table.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-table.h: Table layout widget | ||||
|  * | ||||
|  * 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(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_TABLE_H__ | ||||
| #define __ST_TABLE_H__ | ||||
|  | ||||
| #include <st/st-types.h> | ||||
| #include <st/st-widget.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| /** | ||||
|  * StTableChildOptions: | ||||
|  * @ST_KEEP_ASPECT_RATIO: whether to respect the widget's aspect ratio | ||||
|  * @ST_X_EXPAND: whether to allocate extra space on the widget's x-axis | ||||
|  * @ST_Y_EXPAND: whether to allocate extra space on the widget's y-axis | ||||
|  * @ST_X_FILL: whether to stretch the child to fill the cell horizontally | ||||
|  * @ST_Y_FILL: whether to stretch the child to fill the cell vertically | ||||
|  * | ||||
|  * Denotes the child properties an StTable child will have. | ||||
|  */ | ||||
| typedef enum | ||||
| { | ||||
|   ST_KEEP_ASPECT_RATIO = 1 << 0, | ||||
|   ST_X_EXPAND          = 1 << 1, | ||||
|   ST_Y_EXPAND          = 1 << 2, | ||||
|   ST_X_FILL            = 1 << 3, | ||||
|   ST_Y_FILL            = 1 << 4 | ||||
| } StTableChildOptions; | ||||
|  | ||||
| #define ST_TYPE_TABLE                (st_table_get_type ()) | ||||
| #define ST_TABLE(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_TABLE, StTable)) | ||||
| #define ST_IS_TABLE(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_TABLE)) | ||||
| #define ST_TABLE_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_TABLE, StTableClass)) | ||||
| #define ST_IS_TABLE_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_TABLE)) | ||||
| #define ST_TABLE_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_TABLE, StTableClass)) | ||||
|  | ||||
| typedef struct _StTable              StTable; | ||||
| typedef struct _StTablePrivate       StTablePrivate; | ||||
| typedef struct _StTableClass         StTableClass; | ||||
|  | ||||
| /** | ||||
|  * StTable: | ||||
|  * | ||||
|  * The contents of this structure is private and should only be accessed using | ||||
|  * the provided API. | ||||
|  */ | ||||
| struct _StTable | ||||
| { | ||||
|   /*< private >*/ | ||||
|   StWidget parent_instance; | ||||
|  | ||||
|   StTablePrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _StTableClass | ||||
| { | ||||
|   StWidgetClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType st_table_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| StWidget* st_table_new (void); | ||||
|  | ||||
| gint st_table_get_row_count    (StTable *table); | ||||
| gint st_table_get_column_count (StTable *table); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_TABLE_H__ */ | ||||
							
								
								
									
										451
									
								
								src/st/st-texture-cache.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										451
									
								
								src/st/st-texture-cache.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,451 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-widget.h: Base class for St 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:st-texture-cache | ||||
|  * @short_description: A per-process store to cache textures | ||||
|  * | ||||
|  * #StTextureCache 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 "st-texture-cache.h" | ||||
| #include "st-marshal.h" | ||||
| #include "st-private.h" | ||||
| #include "st-subtexture.h" | ||||
| G_DEFINE_TYPE (StTextureCache, st_texture_cache, G_TYPE_OBJECT) | ||||
|  | ||||
| #define TEXTURE_CACHE_PRIVATE(o) \ | ||||
|   (G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_TEXTURE_CACHE, StTextureCachePrivate)) | ||||
|  | ||||
| typedef struct _StTextureCachePrivate StTextureCachePrivate; | ||||
|  | ||||
| struct _StTextureCachePrivate | ||||
| { | ||||
|   GHashTable *cache; | ||||
| }; | ||||
|  | ||||
| typedef struct FinalizedClosure | ||||
| { | ||||
|   gchar          *path; | ||||
|   StTextureCache *cache; | ||||
| } FinalizedClosure; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
| }; | ||||
|  | ||||
| static StTextureCache* __cache_singleton = NULL; | ||||
|  | ||||
| /* | ||||
|  * Convention: posX with a value of -1 indicates whole texture | ||||
|  */ | ||||
| typedef struct StTextureCacheItem { | ||||
|   char          filename[256]; | ||||
|   int           width, height; | ||||
|   int           posX, posY; | ||||
|   ClutterActor *ptr; | ||||
| } StTextureCacheItem; | ||||
|  | ||||
| static StTextureCacheItem * | ||||
| st_texture_cache_item_new (void) | ||||
| { | ||||
|   return g_slice_new0 (StTextureCacheItem); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_texture_cache_item_free (StTextureCacheItem *item) | ||||
| { | ||||
|   g_slice_free (StTextureCacheItem, item); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_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 | ||||
| st_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 | ||||
| st_texture_cache_dispose (GObject *object) | ||||
| { | ||||
|   if (G_OBJECT_CLASS (st_texture_cache_parent_class)->dispose) | ||||
|     G_OBJECT_CLASS (st_texture_cache_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_texture_cache_finalize (GObject *object) | ||||
| { | ||||
|   StTextureCachePrivate *priv = TEXTURE_CACHE_PRIVATE(object); | ||||
|  | ||||
|   if (priv->cache) | ||||
|     { | ||||
|       g_hash_table_unref (priv->cache); | ||||
|       priv->cache = NULL; | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (st_texture_cache_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_texture_cache_class_init (StTextureCacheClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (StTextureCachePrivate)); | ||||
|  | ||||
|   object_class->get_property = st_texture_cache_get_property; | ||||
|   object_class->set_property = st_texture_cache_set_property; | ||||
|   object_class->dispose = st_texture_cache_dispose; | ||||
|   object_class->finalize = st_texture_cache_finalize; | ||||
|  | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_texture_cache_init (StTextureCache *self) | ||||
| { | ||||
|   StTextureCachePrivate *priv = TEXTURE_CACHE_PRIVATE(self); | ||||
|  | ||||
|   priv->cache = g_hash_table_new_full (g_str_hash, | ||||
|                                        g_str_equal, | ||||
|                                        g_free, | ||||
|                                        NULL); | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_texture_cache_get_default: | ||||
|  * | ||||
|  * Returns the default texture cache. This is owned by St and should not be | ||||
|  * unreferenced or freed. | ||||
|  * | ||||
|  * Returns: (transfer none): a StTextureCache | ||||
|  */ | ||||
| StTextureCache* | ||||
| st_texture_cache_get_default (void) | ||||
| { | ||||
|   if (G_UNLIKELY (__cache_singleton == NULL)) | ||||
|     __cache_singleton = g_object_new (ST_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; | ||||
|   StTextureCachePrivate *priv = TEXTURE_CACHE_PRIVATE(closure->cache); | ||||
|  | ||||
|   g_hash_table_remove (priv->cache, closure->path); | ||||
|  | ||||
|   g_free(closure->path); | ||||
|   g_free(closure); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * st_texture_cache_get_size: | ||||
|  * @self: A #StTextureCache | ||||
|  * | ||||
|  * Returns the number of items in the texture cache | ||||
|  * | ||||
|  * Returns: the current size of the cache | ||||
|  */ | ||||
| gint | ||||
| st_texture_cache_get_size (StTextureCache *self) | ||||
| { | ||||
|   StTextureCachePrivate *priv = TEXTURE_CACHE_PRIVATE(self); | ||||
|  | ||||
|   return g_hash_table_size (priv->cache); | ||||
| } | ||||
|  | ||||
| static void | ||||
| add_texture_to_cache (StTextureCache     *self, | ||||
|                       const gchar        *path, | ||||
|                       StTextureCacheItem *item) | ||||
| { | ||||
|   /*  FinalizedClosure        *closure; */ | ||||
|   StTextureCachePrivate *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 */ | ||||
|  | ||||
| /** | ||||
|  * st_texture_cache_get_texture: | ||||
|  * @self: A #StTextureCache | ||||
|  * @path: A path to a image file | ||||
|  * | ||||
|  * 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* | ||||
| st_texture_cache_get_texture (StTextureCache *self, | ||||
|                               const gchar    *path) | ||||
| { | ||||
|   ClutterActor *texture; | ||||
|   CoglHandle *handle; | ||||
|   StTextureCachePrivate *priv; | ||||
|   StTextureCacheItem *item; | ||||
|  | ||||
|   g_return_val_if_fail (ST_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 && 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 = st_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; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * st_texture_cache_get_actor: | ||||
|  * @self: A #StTextureCache | ||||
|  * @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* | ||||
| st_texture_cache_get_actor (StTextureCache *self, | ||||
|                             const gchar    *path) | ||||
| { | ||||
|   StTextureCachePrivate *priv; | ||||
|   StTextureCacheItem *item; | ||||
|   GError *err = NULL; | ||||
|  | ||||
|   g_return_val_if_fail (ST_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 st_subtexture_new (CLUTTER_TEXTURE (item->ptr), posX, posY, | ||||
|                                 item->width, item->height); | ||||
|     } | ||||
|  | ||||
|   item = st_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 st_subtexture_new (CLUTTER_TEXTURE (item->ptr), 0, 0, item->width, | ||||
|                             item->height); | ||||
| } | ||||
|  | ||||
| void | ||||
| st_texture_cache_load_cache (StTextureCache *self, | ||||
|                              const gchar    *filename) | ||||
| { | ||||
|   FILE *file; | ||||
|   StTextureCacheItem *element, head; | ||||
|   int ret; | ||||
|   ClutterActor *actor; | ||||
|   GError *error = NULL; | ||||
|   StTextureCachePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_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(StTextureCacheItem), 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 = st_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 = st_texture_cache_item_new (); | ||||
|       ret = fread (element, sizeof (StTextureCacheItem), 1, file); | ||||
|       if (ret < 1) | ||||
|         { | ||||
|           /* end of file */ | ||||
|           st_texture_cache_item_free (element); | ||||
|           break; | ||||
|         } | ||||
|  | ||||
|       element->ptr = actor; | ||||
|  | ||||
|       if (g_hash_table_lookup (priv->cache, element->filename)) | ||||
|         { | ||||
|           /* file is already in the cache.... */ | ||||
|           st_texture_cache_item_free (element); | ||||
|         } else { | ||||
|           g_hash_table_insert (priv->cache, element->filename, element); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										96
									
								
								src/st/st-texture-cache.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/st/st-texture-cache.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef _ST_TEXTURE_CACHE | ||||
| #define _ST_TEXTURE_CACHE | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_TEXTURE_CACHE st_texture_cache_get_type() | ||||
|  | ||||
| #define ST_TEXTURE_CACHE(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ | ||||
|   ST_TYPE_TEXTURE_CACHE, StTextureCache)) | ||||
|  | ||||
| #define ST_TEXTURE_CACHE_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_CAST ((klass), \ | ||||
|   ST_TYPE_TEXTURE_CACHE, StTextureCacheClass)) | ||||
|  | ||||
| #define ST_IS_TEXTURE_CACHE(obj) \ | ||||
|   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ | ||||
|   ST_TYPE_TEXTURE_CACHE)) | ||||
|  | ||||
| #define ST_IS_TEXTURE_CACHE_CLASS(klass) \ | ||||
|   (G_TYPE_CHECK_CLASS_TYPE ((klass), \ | ||||
|   ST_TYPE_TEXTURE_CACHE)) | ||||
|  | ||||
| #define ST_TEXTURE_CACHE_GET_CLASS(obj) \ | ||||
|   (G_TYPE_INSTANCE_GET_CLASS ((obj), \ | ||||
|   ST_TYPE_TEXTURE_CACHE, StTextureCacheClass)) | ||||
|  | ||||
| /** | ||||
|  * StTextureCache: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| typedef struct { | ||||
|     /*< private >*/ | ||||
|     GObject parent; | ||||
| } StTextureCache; | ||||
|  | ||||
| typedef struct { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   void (* loaded)        (StTextureCache *self, | ||||
|                           const gchar      *path, | ||||
|                           ClutterTexture   *texture); | ||||
|  | ||||
|   void (* error_loading) (StTextureCache *self, | ||||
|                           GError           *error); | ||||
| } StTextureCacheClass; | ||||
|  | ||||
| GType st_texture_cache_get_type (void); | ||||
|  | ||||
| StTextureCache* st_texture_cache_get_default (void); | ||||
|  | ||||
| ClutterTexture* st_texture_cache_get_texture (StTextureCache *self, | ||||
|                                               const gchar    *path); | ||||
| ClutterActor*   st_texture_cache_get_actor   (StTextureCache *self, | ||||
|                                               const gchar    *path); | ||||
|  | ||||
| gint            st_texture_cache_get_size    (StTextureCache *self); | ||||
|  | ||||
| void st_texture_cache_load_cache (StTextureCache *self, | ||||
|                                   const char     *filename); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* _ST_TEXTURE_CACHE */ | ||||
							
								
								
									
										621
									
								
								src/st/st-texture-frame.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										621
									
								
								src/st/st-texture-frame.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,621 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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:st-texture-frame | ||||
|  * @short_description: Stretch a texture to fit the entire allocation | ||||
|  * | ||||
|  * #StTextureFrame | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
|  | ||||
| #include "st-texture-frame.h" | ||||
| #include "st-private.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_PARENT_TEXTURE, | ||||
|  | ||||
|   PROP_TOP, | ||||
|   PROP_RIGHT, | ||||
|   PROP_BOTTOM, | ||||
|   PROP_LEFT | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (StTextureFrame, st_texture_frame, CLUTTER_TYPE_ACTOR); | ||||
|  | ||||
| #define ST_TEXTURE_FRAME_GET_PRIVATE(obj)     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_TEXTURE_FRAME, StTextureFramePrivate)) | ||||
|  | ||||
| struct _StTextureFramePrivate | ||||
| { | ||||
|   ClutterTexture *parent_texture; | ||||
|  | ||||
|   gfloat          top; | ||||
|   gfloat          right; | ||||
|   gfloat          bottom; | ||||
|   gfloat          left; | ||||
| }; | ||||
|  | ||||
| static void | ||||
| st_texture_frame_get_preferred_width (ClutterActor *self, | ||||
|                                       gfloat        for_height, | ||||
|                                       gfloat       *min_width_p, | ||||
|                                       gfloat       *natural_width_p) | ||||
| { | ||||
|   StTextureFramePrivate *priv = ST_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 | ||||
| st_texture_frame_get_preferred_height (ClutterActor *self, | ||||
|                                        gfloat        for_width, | ||||
|                                        gfloat       *min_height_p, | ||||
|                                        gfloat       *natural_height_p) | ||||
| { | ||||
|   StTextureFramePrivate *priv = ST_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 | ||||
| st_texture_frame_paint (ClutterActor *self) | ||||
| { | ||||
|   StTextureFramePrivate *priv = ST_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 | ||||
| st_texture_frame_set_frame_internal (StTextureFrame *frame, | ||||
|                                      gfloat          top, | ||||
|                                      gfloat          right, | ||||
|                                      gfloat          bottom, | ||||
|                                      gfloat          left) | ||||
| { | ||||
|   StTextureFramePrivate *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 | ||||
| st_texture_frame_set_property (GObject      *gobject, | ||||
|                                guint         prop_id, | ||||
|                                const GValue *value, | ||||
|                                GParamSpec   *pspec) | ||||
| { | ||||
|   StTextureFrame *frame = ST_TEXTURE_FRAME (gobject); | ||||
|   StTextureFramePrivate *priv = frame->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_PARENT_TEXTURE: | ||||
|       st_texture_frame_set_parent_texture (frame, | ||||
|                                            g_value_get_object (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TOP: | ||||
|       st_texture_frame_set_frame_internal (frame, | ||||
|                                            g_value_get_float (value), | ||||
|                                            priv->right, | ||||
|                                            priv->bottom, | ||||
|                                            priv->left); | ||||
|       break; | ||||
|  | ||||
|     case PROP_RIGHT: | ||||
|       st_texture_frame_set_frame_internal (frame, | ||||
|                                            priv->top, | ||||
|                                            g_value_get_float (value), | ||||
|                                            priv->bottom, | ||||
|                                            priv->left); | ||||
|       break; | ||||
|  | ||||
|     case PROP_BOTTOM: | ||||
|       st_texture_frame_set_frame_internal (frame, | ||||
|                                            priv->top, | ||||
|                                            priv->right, | ||||
|                                            g_value_get_float (value), | ||||
|                                            priv->left); | ||||
|       break; | ||||
|  | ||||
|     case PROP_LEFT: | ||||
|       st_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 | ||||
| st_texture_frame_get_property (GObject    *gobject, | ||||
|                                guint       prop_id, | ||||
|                                GValue     *value, | ||||
|                                GParamSpec *pspec) | ||||
| { | ||||
|   StTextureFramePrivate *priv = ST_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 | ||||
| st_texture_frame_dispose (GObject *gobject) | ||||
| { | ||||
|   StTextureFramePrivate *priv = ST_TEXTURE_FRAME (gobject)->priv; | ||||
|  | ||||
|   if (priv->parent_texture) | ||||
|     { | ||||
|       g_object_unref (priv->parent_texture); | ||||
|       priv->parent_texture = NULL; | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (st_texture_frame_parent_class)->dispose (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_texture_frame_class_init (StTextureFrameClass *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 (StTextureFramePrivate)); | ||||
|  | ||||
|   actor_class->get_preferred_width = | ||||
|     st_texture_frame_get_preferred_width; | ||||
|   actor_class->get_preferred_height = | ||||
|     st_texture_frame_get_preferred_height; | ||||
|   actor_class->paint = st_texture_frame_paint; | ||||
|  | ||||
|   gobject_class->set_property = st_texture_frame_set_property; | ||||
|   gobject_class->get_property = st_texture_frame_get_property; | ||||
|   gobject_class->dispose = st_texture_frame_dispose; | ||||
|  | ||||
|   pspec = g_param_spec_object ("parent-texture", | ||||
|                                "Parent Texture", | ||||
|                                "The parent ClutterTexture", | ||||
|                                CLUTTER_TYPE_TEXTURE, | ||||
|                                ST_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, | ||||
|                               ST_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, | ||||
|                               ST_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, | ||||
|                               ST_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, | ||||
|                               ST_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_RIGHT, pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_texture_frame_init (StTextureFrame *self) | ||||
| { | ||||
|   StTextureFramePrivate *priv; | ||||
|  | ||||
|   self->priv = priv = ST_TEXTURE_FRAME_GET_PRIVATE (self); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_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 #StTextureFrame is a specialized texture that efficiently clones | ||||
|  * an area of the given @texture while keeping preserving portions of the | ||||
|  * same texture. | ||||
|  * | ||||
|  * A #StTextureFrame can be used to make a rectangular texture fit a | ||||
|  * given size without stretching its borders. | ||||
|  * | ||||
|  * Return value: the newly created #StTextureFrame | ||||
|  */ | ||||
| ClutterActor* | ||||
| st_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 (ST_TYPE_TEXTURE_FRAME, | ||||
|                        "parent-texture", texture, | ||||
|                        "top", top, | ||||
|                        "right", right, | ||||
|                        "bottom", bottom, | ||||
|                        "left", left, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_texture_frame_get_parent_texture: | ||||
|  * @frame: A #StTextureFrame | ||||
|  * | ||||
|  * Return the texture used by the #StTextureFrame | ||||
|  * | ||||
|  * Returns: (transfer none): a #ClutterTexture owned by the #StTextureFrame | ||||
|  */ | ||||
| ClutterTexture * | ||||
| st_texture_frame_get_parent_texture (StTextureFrame *frame) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_TEXTURE_FRAME (frame), NULL); | ||||
|  | ||||
|   return frame->priv->parent_texture; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_texture_frame_set_parent_texture: | ||||
|  * @frame: A #StTextureFrame | ||||
|  * @texture: A #ClutterTexture | ||||
|  * | ||||
|  * Set the #ClutterTexture used by this #StTextureFrame | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| st_texture_frame_set_parent_texture (StTextureFrame *frame, | ||||
|                                      ClutterTexture *texture) | ||||
| { | ||||
|   StTextureFramePrivate *priv; | ||||
|   gboolean was_visible; | ||||
|  | ||||
|   g_return_if_fail (ST_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"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_texture_frame_set_frame: | ||||
|  * @frame: A #StTextureFrame | ||||
|  * @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 | ||||
| st_texture_frame_set_frame (StTextureFrame *frame, | ||||
|                             gfloat          top, | ||||
|                             gfloat          right, | ||||
|                             gfloat          bottom, | ||||
|                             gfloat          left) | ||||
| { | ||||
|   g_return_if_fail (ST_IS_TEXTURE_FRAME (frame)); | ||||
|  | ||||
|   st_texture_frame_set_frame_internal (frame, top, right, bottom, left); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_texture_frame_get_frame: | ||||
|  * @frame: A #StTextureFrame | ||||
|  * @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 | ||||
| st_texture_frame_get_frame (StTextureFrame *frame, | ||||
|                             gfloat         *top, | ||||
|                             gfloat         *right, | ||||
|                             gfloat         *bottom, | ||||
|                             gfloat         *left) | ||||
| { | ||||
|   StTextureFramePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_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; | ||||
| } | ||||
							
								
								
									
										94
									
								
								src/st/st-texture-frame.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/st/st-texture-frame.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_TEXTURE_FRAME_H__ | ||||
| #define __ST_TEXTURE_FRAME_H__ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_TEXTURE_FRAME                 (st_texture_frame_get_type ()) | ||||
| #define ST_TEXTURE_FRAME(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_TEXTURE_FRAME, StTextureFrame)) | ||||
| #define ST_TEXTURE_FRAME_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_TEXTURE_FRAME, StTextureFrameClass)) | ||||
| #define ST_IS_TEXTURE_FRAME(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_TEXTURE_FRAME)) | ||||
| #define ST_IS_TEXTURE_FRAME_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_TEXTURE_FRAME)) | ||||
| #define ST_TEXTURE_FRAME_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_TEXTURE_FRAME, StTextureFrameClass)) | ||||
|  | ||||
| typedef struct _StTextureFrame                StTextureFrame; | ||||
| typedef struct _StTextureFramePrivate         StTextureFramePrivate; | ||||
| typedef struct _StTextureFrameClass           StTextureFrameClass; | ||||
|  | ||||
| /** | ||||
|  * StTextureFrame: | ||||
|  * | ||||
|  * The contents of this structure are private and should only be accessed | ||||
|  * through the public API. | ||||
|  */ | ||||
| struct _StTextureFrame | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActor parent_instance; | ||||
|    | ||||
|   StTextureFramePrivate    *priv; | ||||
| }; | ||||
|  | ||||
| struct _StTextureFrameClass  | ||||
| { | ||||
|   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 st_texture_frame_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| ClutterActor *  st_texture_frame_new                (ClutterTexture *texture, | ||||
|                                                      gfloat          top, | ||||
|                                                      gfloat          right, | ||||
|                                                      gfloat          bottom, | ||||
|                                                      gfloat          left); | ||||
| void            st_texture_frame_set_parent_texture (StTextureFrame *frame, | ||||
|                                                      ClutterTexture *texture); | ||||
| ClutterTexture *st_texture_frame_get_parent_texture (StTextureFrame *frame); | ||||
| void            st_texture_frame_set_frame          (StTextureFrame *frame, | ||||
|                                                      gfloat          top, | ||||
|                                                      gfloat          right, | ||||
|                                                      gfloat          bottom, | ||||
|                                                      gfloat          left); | ||||
| void            st_texture_frame_get_frame          (StTextureFrame *frame, | ||||
|                                                      gfloat         *top, | ||||
|                                                      gfloat         *right, | ||||
|                                                      gfloat         *bottom, | ||||
|                                                      gfloat         *left); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_TEXTURE_FRAME_H__ */ | ||||
							
								
								
									
										218
									
								
								src/st/st-theme-context.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								src/st/st-theme-context.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,218 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include "st-theme.h" | ||||
| #include "st-theme-context.h" | ||||
|  | ||||
| struct _StThemeContext { | ||||
|   GObject parent; | ||||
|  | ||||
|   double resolution; | ||||
|   PangoFontDescription *font; | ||||
|   StThemeNode *root_node; | ||||
|   StTheme *theme; | ||||
| }; | ||||
|  | ||||
| struct _StThemeContextClass { | ||||
|   GObjectClass parent_class; | ||||
| }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   CHANGED, | ||||
|  | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL] = { 0, }; | ||||
|  | ||||
| G_DEFINE_TYPE (StThemeContext, st_theme_context, G_TYPE_OBJECT) | ||||
|  | ||||
| static void | ||||
| st_theme_context_finalize (GObject *object) | ||||
| { | ||||
|   StThemeContext *context = ST_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 (st_theme_context_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_theme_context_class_init (StThemeContextClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = st_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 | ||||
| st_theme_context_init (StThemeContext *context) | ||||
| { | ||||
|   context->resolution = 96.; | ||||
|   context->font = pango_font_description_from_string ("sans-serif 10"); | ||||
| } | ||||
|  | ||||
| StThemeContext * | ||||
| st_theme_context_new (void) | ||||
| { | ||||
|   StThemeContext *context; | ||||
|  | ||||
|   context = g_object_new (ST_TYPE_THEME_CONTEXT, NULL); | ||||
|  | ||||
|   return context; | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_stage_destroy (ClutterStage *stage) | ||||
| { | ||||
|   StThemeContext *context = st_theme_context_get_for_stage (stage); | ||||
|  | ||||
|   g_object_set_data (G_OBJECT (stage), "st-theme-context", NULL); | ||||
|   g_object_unref (context); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_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 | ||||
|  */ | ||||
| StThemeContext * | ||||
| st_theme_context_get_for_stage (ClutterStage *stage) | ||||
| { | ||||
|   StThemeContext *context; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); | ||||
|  | ||||
|   context = g_object_get_data (G_OBJECT (stage), "st-theme-context"); | ||||
|   if (context) | ||||
|     return context; | ||||
|  | ||||
|   context = st_theme_context_new (); | ||||
|   g_object_set_data (G_OBJECT (stage), "st-theme-context", context); | ||||
|   g_signal_connect (stage, "destroy", | ||||
|                     G_CALLBACK (on_stage_destroy), NULL); | ||||
|  | ||||
|   return context; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_theme_context_set_theme: | ||||
|  * @context: a #StThemeContext | ||||
|  * | ||||
|  * 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 | ||||
| st_theme_context_set_theme (StThemeContext          *context, | ||||
|                             StTheme                 *theme) | ||||
| { | ||||
|   g_return_if_fail (ST_IS_THEME_CONTEXT (context)); | ||||
|   g_return_if_fail (theme == NULL || ST_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); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_theme_context_get_theme: | ||||
|  * @context: a #StThemeContext | ||||
|  * | ||||
|  * Gets the default theme for the context. See st_theme_context_set_theme() | ||||
|  * | ||||
|  * Return value: (transfer none): the default theme for the context | ||||
|  */ | ||||
| StTheme * | ||||
| st_theme_context_get_theme (StThemeContext *context) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_THEME_CONTEXT (context), NULL); | ||||
|  | ||||
|   return context->theme; | ||||
| } | ||||
|  | ||||
| void | ||||
| st_theme_context_set_resolution (StThemeContext *context, | ||||
|                                  double          resolution) | ||||
| { | ||||
|   g_return_if_fail (ST_IS_THEME_CONTEXT (context)); | ||||
|  | ||||
|   context->resolution = resolution; | ||||
| } | ||||
|  | ||||
| double | ||||
| st_theme_context_get_resolution (StThemeContext *context) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_THEME_CONTEXT (context), 96.); | ||||
|  | ||||
|   return context->resolution; | ||||
| } | ||||
|  | ||||
| void | ||||
| st_theme_context_set_font (StThemeContext             *context, | ||||
|                            const PangoFontDescription *font) | ||||
| { | ||||
|   g_return_if_fail (ST_IS_THEME_CONTEXT (context)); | ||||
|  | ||||
|   if (context->font == font) | ||||
|     return; | ||||
|  | ||||
|   pango_font_description_free (context->font); | ||||
|   context->font = pango_font_description_copy (font); | ||||
| } | ||||
|  | ||||
| const PangoFontDescription * | ||||
| st_theme_context_get_font (StThemeContext *context) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_THEME_CONTEXT (context), NULL); | ||||
|  | ||||
|   return context->font; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_theme_context_get_root_node: | ||||
|  * @context: a #StThemeContext | ||||
|  * | ||||
|  * 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 | ||||
|  */ | ||||
| StThemeNode * | ||||
| st_theme_context_get_root_node (StThemeContext *context) | ||||
| { | ||||
|   if (context->root_node == NULL) | ||||
|     context->root_node = st_theme_node_new (context, NULL, context->theme, | ||||
|                                             G_TYPE_NONE, NULL, NULL, NULL, NULL); | ||||
|  | ||||
|   return context->root_node; | ||||
| } | ||||
							
								
								
									
										40
									
								
								src/st/st-theme-context.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/st/st-theme-context.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| #ifndef __ST_THEME_CONTEXT_H__ | ||||
| #define __ST_THEME_CONTEXT_H__ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <pango/pango.h> | ||||
| #include "st-theme-node.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| typedef struct _StThemeContextClass StThemeContextClass; | ||||
|  | ||||
| #define ST_TYPE_THEME_CONTEXT             (st_theme_context_get_type ()) | ||||
| #define ST_THEME_CONTEXT(object)          (G_TYPE_CHECK_INSTANCE_CAST ((object), ST_TYPE_THEME_CONTEXT, StThemeContext)) | ||||
| #define ST_THEME_CONTEXT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_THEME_CONTEXT, StThemeContextClass)) | ||||
| #define ST_IS_THEME_CONTEXT(object)       (G_TYPE_CHECK_INSTANCE_TYPE ((object), ST_TYPE_THEME_CONTEXT)) | ||||
| #define ST_IS_THEME_CONTEXT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_THEME_CONTEXT)) | ||||
| #define ST_THEME_CONTEXT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_THEME_CONTEXT, StThemeContextClass)) | ||||
|  | ||||
| GType st_theme_context_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| StThemeContext *st_theme_context_new           (void); | ||||
| StThemeContext *st_theme_context_get_for_stage (ClutterStage *stage); | ||||
|  | ||||
| void                        st_theme_context_set_theme      (StThemeContext             *context, | ||||
|                                                              StTheme                    *theme); | ||||
| StTheme *                   st_theme_context_get_theme      (StThemeContext             *context); | ||||
|  | ||||
| void                        st_theme_context_set_resolution (StThemeContext             *context, | ||||
|                                                              gdouble                     resolution); | ||||
| double                      st_theme_context_get_resolution (StThemeContext             *context); | ||||
| void                        st_theme_context_set_font       (StThemeContext             *context, | ||||
|                                                              const PangoFontDescription *font); | ||||
| const PangoFontDescription *st_theme_context_get_font       (StThemeContext             *context); | ||||
|  | ||||
| StThemeNode *               st_theme_context_get_root_node  (StThemeContext             *context); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_THEME_CONTEXT_H__ */ | ||||
							
								
								
									
										2113
									
								
								src/st/st-theme-node.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2113
									
								
								src/st/st-theme-node.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										143
									
								
								src/st/st-theme-node.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								src/st/st-theme-node.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| #ifndef __ST_THEME_NODE_H__ | ||||
| #define __ST_THEME_NODE_H__ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include "st-border-image.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| typedef struct _StTheme          StTheme; | ||||
| typedef struct _StThemeContext   StThemeContext; | ||||
|  | ||||
| typedef struct _StThemeNode      StThemeNode; | ||||
| typedef struct _StThemeNodeClass StThemeNodeClass; | ||||
|  | ||||
| #define ST_TYPE_THEME_NODE              (st_theme_node_get_type ()) | ||||
| #define ST_THEME_NODE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), ST_TYPE_THEME_NODE, StThemeNode)) | ||||
| #define ST_THEME_NODE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass),     ST_TYPE_THEME_NODE, StThemeNodeClass)) | ||||
| #define ST_IS_THEME_NODE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), ST_TYPE_THEME_NODE)) | ||||
| #define ST_IS_THEME_NODE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass),     ST_TYPE_THEME_NODE)) | ||||
| #define ST_THEME_NODE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj),     ST_TYPE_THEME_NODE, StThemeNodeClass)) | ||||
|  | ||||
| typedef enum { | ||||
|     ST_SIDE_TOP, | ||||
|     ST_SIDE_RIGHT, | ||||
|     ST_SIDE_BOTTOM, | ||||
|     ST_SIDE_LEFT | ||||
| } StSide; | ||||
|  | ||||
| typedef enum { | ||||
|     ST_CORNER_TOPLEFT, | ||||
|     ST_CORNER_TOPRIGHT, | ||||
|     ST_CORNER_BOTTOMRIGHT, | ||||
|     ST_CORNER_BOTTOMLEFT | ||||
| } StCorner; | ||||
|  | ||||
| /* These are the CSS values; that doesn't mean we have to implement blink... */ | ||||
| typedef enum { | ||||
|     ST_TEXT_DECORATION_UNDERLINE    = 1 << 0, | ||||
|     ST_TEXT_DECORATION_OVERLINE     = 1 << 1, | ||||
|     ST_TEXT_DECORATION_LINE_THROUGH = 1 << 2, | ||||
|     ST_TEXT_DECORATION_BLINK        = 1 << 3 | ||||
| } StTextDecoration; | ||||
|  | ||||
| GType st_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' | ||||
|  */ | ||||
| StThemeNode *st_theme_node_new (StThemeContext *context, | ||||
|                                 StThemeNode    *parent_node,   /* can be null */ | ||||
|                                 StTheme        *theme,         /* can be null */ | ||||
|                                 GType           element_type, | ||||
|                                 const char     *element_id, | ||||
|                                 const char     *element_class, | ||||
|                                 const char     *pseudo_class, | ||||
|                                 const char     *inline_style); | ||||
|  | ||||
| StThemeNode *st_theme_node_get_parent (StThemeNode *node); | ||||
|  | ||||
| StTheme *st_theme_node_get_theme (StThemeNode *node); | ||||
|  | ||||
| GType       st_theme_node_get_element_type  (StThemeNode *node); | ||||
| const char *st_theme_node_get_element_id    (StThemeNode *node); | ||||
| const char *st_theme_node_get_element_class (StThemeNode *node); | ||||
| const char *st_theme_node_get_pseudo_class  (StThemeNode *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 st_theme_node_get_color  (StThemeNode  *node, | ||||
|                                    const char   *property_name, | ||||
|                                    gboolean      inherit, | ||||
|                                    ClutterColor *color); | ||||
|  | ||||
| gboolean st_theme_node_get_double (StThemeNode  *node, | ||||
|                                    const char   *property_name, | ||||
|                                    gboolean      inherit, | ||||
|                                    double       *value); | ||||
|  | ||||
| /* The length here is already resolved to pixels | ||||
|  */ | ||||
| gboolean st_theme_node_get_length (StThemeNode *node, | ||||
|                                    const char  *property_name, | ||||
|                                    gboolean     inherit, | ||||
|                                    gdouble     *length); | ||||
|  | ||||
| /* Specific getters for particular properties: cached | ||||
|  */ | ||||
| void st_theme_node_get_background_color (StThemeNode  *node, | ||||
|                                          ClutterColor *color); | ||||
| void st_theme_node_get_foreground_color (StThemeNode  *node, | ||||
|                                          ClutterColor *color); | ||||
|  | ||||
| const char *st_theme_node_get_background_image (StThemeNode *node); | ||||
|  | ||||
| double st_theme_node_get_border_width  (StThemeNode  *node, | ||||
|                                         StSide        side); | ||||
| double st_theme_node_get_border_radius (StThemeNode  *node, | ||||
|                                         StCorner      corner); | ||||
| void   st_theme_node_get_border_color  (StThemeNode  *node, | ||||
|                                         StSide        side, | ||||
|                                         ClutterColor *color); | ||||
|  | ||||
| double st_theme_node_get_padding       (StThemeNode  *node, | ||||
|                                         StSide        side); | ||||
|  | ||||
| StTextDecoration st_theme_node_get_text_decoration (StThemeNode *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 *st_theme_node_get_font (StThemeNode *node); | ||||
|  | ||||
| StBorderImage *st_theme_node_get_border_image (StThemeNode *node); | ||||
|  | ||||
| /* Helpers for get_preferred_width()/get_preferred_height() ClutterActor vfuncs */ | ||||
| void st_theme_node_adjust_for_height       (StThemeNode  *node, | ||||
|                                             float        *for_height); | ||||
| void st_theme_node_adjust_preferred_width  (StThemeNode  *node, | ||||
|                                             float        *min_width_p, | ||||
|                                             float        *natural_width_p); | ||||
| void st_theme_node_adjust_for_width        (StThemeNode  *node, | ||||
|                                             float        *for_width); | ||||
| void st_theme_node_adjust_preferred_height (StThemeNode  *node, | ||||
|                                             float        *min_height_p, | ||||
|                                             float        *natural_height_p); | ||||
|  | ||||
| /* Helper for allocate() ClutterActor vfunc */ | ||||
| void st_theme_node_get_content_box         (StThemeNode        *node, | ||||
|                                             const ClutterActorBox *actor_box, | ||||
|                                             ClutterActorBox       *content_box); | ||||
|  | ||||
| gboolean st_theme_node_geometry_equal (StThemeNode *node, | ||||
|                                        StThemeNode *other); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_THEME_NODE_H__ */ | ||||
							
								
								
									
										20
									
								
								src/st/st-theme-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/st/st-theme-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| #ifndef __ST_THEME_PRIVATE_H__ | ||||
| #define __ST_THEME_PRIVATE_H__ | ||||
|  | ||||
| #include <libcroco/libcroco.h> | ||||
| #include "st-theme.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| GPtrArray *_st_theme_get_matched_properties (StTheme       *theme, | ||||
|                                              StThemeNode   *node); | ||||
|  | ||||
| /* Resolve an URL from the stylesheet to a filename */ | ||||
| char *_st_theme_resolve_url (StTheme      *theme, | ||||
|                              CRStyleSheet *base_stylesheet, | ||||
|                              const char   *url); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_THEME_PRIVATE_H__ */ | ||||
							
								
								
									
										1029
									
								
								src/st/st-theme.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1029
									
								
								src/st/st-theme.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										28
									
								
								src/st/st-theme.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/st/st-theme.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| #ifndef __ST_THEME_H__ | ||||
| #define __ST_THEME_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include "st-theme-node.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| typedef struct _StThemeClass StThemeClass; | ||||
|  | ||||
| #define ST_TYPE_THEME              (st_theme_get_type ()) | ||||
| #define ST_THEME(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), ST_TYPE_THEME, StTheme)) | ||||
| #define ST_THEME_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_THEME, StThemeClass)) | ||||
| #define ST_IS_THEME(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), ST_TYPE_THEME)) | ||||
| #define ST_IS_THEME_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_THEME)) | ||||
| #define ST_THEME_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_THEME, StThemeClass)) | ||||
|  | ||||
| GType  st_theme_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| StTheme *st_theme_new (const char *application_stylesheet, | ||||
|                        const char *theme_stylesheet, | ||||
|                        const char *default_stylesheet); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_THEME_H__ */ | ||||
							
								
								
									
										665
									
								
								src/st/st-tooltip.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										665
									
								
								src/st/st-tooltip.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,665 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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:st-tooltip | ||||
|  * @short_description: A tooltip widget | ||||
|  * | ||||
|  * #StTooltip implements a single tooltip. It should not normally be created | ||||
|  * by the application but by the widget implementing tooltip capabilities, for | ||||
|  * example, #st_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 "st-tooltip.h" | ||||
|  | ||||
| #include "st-widget.h" | ||||
| #include "st-private.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_LABEL, | ||||
|   PROP_TIP_AREA | ||||
| }; | ||||
|  | ||||
| #define ST_TOOLTIP_GET_PRIVATE(obj)    \ | ||||
|   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_TOOLTIP, StTooltipPrivate)) | ||||
|  | ||||
| struct _StTooltipPrivate | ||||
| { | ||||
|   ClutterActor    *label; | ||||
|  | ||||
|   gfloat           arrow_offset; | ||||
|   gboolean         actor_below; | ||||
|  | ||||
|   ClutterGeometry *tip_area; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (StTooltip, st_tooltip, ST_TYPE_WIDGET); | ||||
|  | ||||
| static void | ||||
| st_tooltip_set_property (GObject      *gobject, | ||||
|                          guint         prop_id, | ||||
|                          const GValue *value, | ||||
|                          GParamSpec   *pspec) | ||||
| { | ||||
|   StTooltip *tooltip = ST_TOOLTIP (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_LABEL: | ||||
|       st_tooltip_set_label (tooltip, g_value_get_string (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_TIP_AREA: | ||||
|       st_tooltip_set_tip_area (tooltip, g_value_get_boxed (value)); | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_tooltip_get_property (GObject    *gobject, | ||||
|                          guint       prop_id, | ||||
|                          GValue     *value, | ||||
|                          GParamSpec *pspec) | ||||
| { | ||||
|   StTooltipPrivate *priv = ST_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 | ||||
| st_tooltip_style_changed (StWidget *self) | ||||
| { | ||||
|   StTooltipPrivate *priv; | ||||
|   StThemeNode *theme_node; | ||||
|   ClutterColor color; | ||||
|   const PangoFontDescription *font; | ||||
|   gchar *font_string; | ||||
|  | ||||
|   priv = ST_TOOLTIP (self)->priv; | ||||
|   theme_node = st_widget_get_theme_node (self); | ||||
|  | ||||
|   st_theme_node_get_foreground_color (theme_node, &color); | ||||
|   clutter_text_set_color (CLUTTER_TEXT (priv->label), &color); | ||||
|  | ||||
|   font = st_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); | ||||
|  | ||||
|   ST_WIDGET_CLASS (st_tooltip_parent_class)->style_changed (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_tooltip_get_preferred_width (ClutterActor *self, | ||||
|                                 gfloat        for_height, | ||||
|                                 gfloat       *min_width_p, | ||||
|                                 gfloat       *natural_width_p) | ||||
| { | ||||
|   StTooltipPrivate *priv = ST_TOOLTIP (self)->priv; | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self)); | ||||
|   gfloat min_label_w, natural_label_w; | ||||
|   gfloat label_height, arrow_height; | ||||
|   ClutterActor *arrow_image; | ||||
|  | ||||
|   st_theme_node_adjust_for_height (theme_node, &for_height); | ||||
|  | ||||
|   arrow_image = st_widget_get_background_image (ST_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; | ||||
|     } | ||||
|  | ||||
|   st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_tooltip_get_preferred_height (ClutterActor *self, | ||||
|                                  gfloat        for_width, | ||||
|                                  gfloat       *min_height_p, | ||||
|                                  gfloat       *natural_height_p) | ||||
| { | ||||
|   StTooltipPrivate *priv = ST_TOOLTIP (self)->priv; | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self)); | ||||
|   gfloat arrow_height; | ||||
|   gfloat min_label_h, natural_label_h; | ||||
|   ClutterActor *arrow_image; | ||||
|  | ||||
|   st_theme_node_adjust_for_width (theme_node, &for_width); | ||||
|  | ||||
|   arrow_image = st_widget_get_background_image (ST_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; | ||||
|  | ||||
|   st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_tooltip_allocate (ClutterActor          *self, | ||||
|                      const ClutterActorBox *box, | ||||
|                      ClutterAllocationFlags flags) | ||||
| { | ||||
|   StTooltipPrivate *priv = ST_TOOLTIP (self)->priv; | ||||
|   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self)); | ||||
|   ClutterActorBox content_box, child_box, arrow_box; | ||||
|   gfloat arrow_height, arrow_width; | ||||
|   ClutterActor *border_image, *arrow_image; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (st_tooltip_parent_class)->allocate (self, | ||||
|                                                            box, | ||||
|                                                            flags); | ||||
|  | ||||
|   st_theme_node_get_content_box (theme_node, box, &content_box); | ||||
|  | ||||
|   arrow_image = st_widget_get_background_image (ST_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 = st_widget_get_border_image (ST_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 | ||||
| st_tooltip_paint (ClutterActor *self) | ||||
| { | ||||
|   ClutterActor *border_image, *arrow_image; | ||||
|   StTooltipPrivate *priv = ST_TOOLTIP (self)->priv; | ||||
|  | ||||
|   border_image = st_widget_get_border_image (ST_WIDGET (self)); | ||||
|   if (border_image) | ||||
|     clutter_actor_paint (border_image); | ||||
|  | ||||
|   arrow_image = st_widget_get_background_image (ST_WIDGET (self)); | ||||
|   if (arrow_image && !priv->actor_below) | ||||
|     clutter_actor_paint (arrow_image); | ||||
|  | ||||
|   clutter_actor_paint (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_tooltip_map (ClutterActor *self) | ||||
| { | ||||
|   StTooltipPrivate *priv = ST_TOOLTIP (self)->priv; | ||||
|   ClutterActor *border_image, *arrow_image; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (st_tooltip_parent_class)->map (self); | ||||
|  | ||||
|   border_image = st_widget_get_border_image (ST_WIDGET (self)); | ||||
|   if (border_image) | ||||
|     clutter_actor_map (border_image); | ||||
|  | ||||
|   arrow_image = st_widget_get_background_image (ST_WIDGET (self)); | ||||
|   if (arrow_image) | ||||
|     clutter_actor_map (arrow_image); | ||||
|  | ||||
|   clutter_actor_map (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_tooltip_unmap (ClutterActor *self) | ||||
| { | ||||
|   StTooltipPrivate *priv = ST_TOOLTIP (self)->priv; | ||||
|   ClutterActor *border_image, *arrow_image; | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (st_tooltip_parent_class)->unmap (self); | ||||
|  | ||||
|   border_image = st_widget_get_border_image (ST_WIDGET (self)); | ||||
|   if (border_image) | ||||
|     clutter_actor_unmap (border_image); | ||||
|  | ||||
|   arrow_image = st_widget_get_background_image (ST_WIDGET (self)); | ||||
|   if (arrow_image) | ||||
|     clutter_actor_unmap (arrow_image); | ||||
|  | ||||
|   clutter_actor_unmap (priv->label); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_tooltip_class_init (StTooltipClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   StWidgetClass *widget_class = ST_WIDGET_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (StTooltipPrivate)); | ||||
|  | ||||
|   gobject_class->set_property = st_tooltip_set_property; | ||||
|   gobject_class->get_property = st_tooltip_get_property; | ||||
|  | ||||
|   actor_class->get_preferred_width = st_tooltip_get_preferred_width; | ||||
|   actor_class->get_preferred_height = st_tooltip_get_preferred_height; | ||||
|   actor_class->allocate = st_tooltip_allocate; | ||||
|   actor_class->paint = st_tooltip_paint; | ||||
|   actor_class->map = st_tooltip_map; | ||||
|   actor_class->unmap = st_tooltip_unmap; | ||||
|  | ||||
|   widget_class->style_changed = st_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, | ||||
|                               ST_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_TIP_AREA, pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_tooltip_init (StTooltip *tooltip) | ||||
| { | ||||
|   tooltip->priv = ST_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 | ||||
| st_tooltip_update_position (StTooltip *tooltip) | ||||
| { | ||||
|   StTooltipPrivate *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 */ | ||||
|   st_widget_ensure_style ((StWidget *) 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); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_tooltip_get_label: | ||||
|  * @tooltip: a #StTooltip | ||||
|  * | ||||
|  * 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 * | ||||
| st_tooltip_get_label (StTooltip *tooltip) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_TOOLTIP (tooltip), NULL); | ||||
|  | ||||
|   return clutter_text_get_text (CLUTTER_TEXT (tooltip->priv->label)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_tooltip_set_label: | ||||
|  * @tooltip: a #StTooltip | ||||
|  * @text: text to set the label to | ||||
|  * | ||||
|  * Sets the text displayed on the tooltip | ||||
|  */ | ||||
| void | ||||
| st_tooltip_set_label (StTooltip   *tooltip, | ||||
|                       const gchar *text) | ||||
| { | ||||
|   StTooltipPrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_TOOLTIP (tooltip)); | ||||
|  | ||||
|   priv = tooltip->priv; | ||||
|  | ||||
|   clutter_text_set_text (CLUTTER_TEXT (priv->label), text); | ||||
|  | ||||
|   g_object_notify (G_OBJECT (tooltip), "label"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_tooltip_show: | ||||
|  * @tooltip: a #StTooltip | ||||
|  * | ||||
|  * Show the tooltip relative to the associated widget. | ||||
|  */ | ||||
| void | ||||
| st_tooltip_show (StTooltip *tooltip) | ||||
| { | ||||
|   StTooltipPrivate *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 ("StTooltip 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); | ||||
|  | ||||
|   st_tooltip_update_position (tooltip); | ||||
|  | ||||
|   /* finally show the tooltip... */ | ||||
|   CLUTTER_ACTOR_CLASS (st_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 | ||||
| st_tooltip_hide_complete (ClutterAnimation *animation, | ||||
|                           ClutterActor     *actor) | ||||
| { | ||||
|   CLUTTER_ACTOR_CLASS (st_tooltip_parent_class)->hide (actor); | ||||
|   g_signal_handlers_disconnect_by_func (actor, | ||||
|                                         st_tooltip_hide_complete, | ||||
|                                         actor); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_tooltip_hide: | ||||
|  * @tooltip: a #StTooltip | ||||
|  * | ||||
|  * Hide the tooltip | ||||
|  */ | ||||
| void | ||||
| st_tooltip_hide (StTooltip *tooltip) | ||||
| { | ||||
|   ClutterAnimation *animation; | ||||
|  | ||||
|   g_return_if_fail (ST_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 (st_tooltip_hide_complete), tooltip); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_tooltip_set_tip_area: | ||||
|  * @tooltip: A #StTooltip | ||||
|  * @area: A #ClutterGeometry | ||||
|  * | ||||
|  * Set the area on the stage that the tooltip applies to. | ||||
|  */ | ||||
| void | ||||
| st_tooltip_set_tip_area (StTooltip             *tooltip, | ||||
|                          const ClutterGeometry *area) | ||||
| { | ||||
|   g_return_if_fail (ST_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); | ||||
|  | ||||
|   st_tooltip_update_position (tooltip); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_tooltip_get_tip_area: | ||||
|  * @tooltip: A #StTooltip | ||||
|  * | ||||
|  * 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* | ||||
| st_tooltip_get_tip_area (StTooltip *tooltip) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_TOOLTIP (tooltip), NULL); | ||||
|  | ||||
|   return tooltip->priv->tip_area; | ||||
| } | ||||
							
								
								
									
										81
									
								
								src/st/st-tooltip.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/st/st-tooltip.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-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(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_TOOLTIP_H__ | ||||
| #define __ST_TOOLTIP_H__ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #include <st/st-bin.h> | ||||
|  | ||||
| #define ST_TYPE_TOOLTIP                (st_tooltip_get_type ()) | ||||
| #define ST_TOOLTIP(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_TOOLTIP, StTooltip)) | ||||
| #define ST_IS_TOOLTIP(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_TOOLTIP)) | ||||
| #define ST_TOOLTIP_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_TOOLTIP, StTooltipClass)) | ||||
| #define ST_IS_TOOLTIP_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_TOOLTIP)) | ||||
| #define ST_TOOLTIP_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_TOOLTIP, StTooltipClass)) | ||||
|  | ||||
| typedef struct _StTooltip              StTooltip; | ||||
| typedef struct _StTooltipPrivate       StTooltipPrivate; | ||||
| typedef struct _StTooltipClass         StTooltipClass; | ||||
|  | ||||
| /** | ||||
|  * StTooltip: | ||||
|  * | ||||
|  * The contents of this structure is private and should only be accessed using | ||||
|  * the provided API. | ||||
|  */ | ||||
| struct _StTooltip | ||||
| { | ||||
|   /*< private >*/ | ||||
|   StBin parent_instance; | ||||
|  | ||||
|   StTooltipPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _StTooltipClass | ||||
| { | ||||
|   StBinClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType st_tooltip_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| G_CONST_RETURN gchar *st_tooltip_get_label (StTooltip   *tooltip); | ||||
| void                  st_tooltip_set_label (StTooltip   *tooltip, | ||||
|                                             const gchar *text); | ||||
| void                  st_tooltip_show      (StTooltip   *tooltip); | ||||
| void                  st_tooltip_hide      (StTooltip   *tooltip); | ||||
|  | ||||
| void                            st_tooltip_set_tip_area (StTooltip             *tooltip, | ||||
|                                                          const ClutterGeometry *area); | ||||
| G_CONST_RETURN ClutterGeometry* st_tooltip_get_tip_area (StTooltip             *tooltip); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_TOOLTIP_H__ */ | ||||
							
								
								
									
										48
									
								
								src/st/st-types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/st/st-types.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * 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. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:st-types | ||||
|  * @short_description: type definitions used throughout St | ||||
|  * | ||||
|  * Common types for StWidgets. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_TYPES_H__ | ||||
| #define __ST_TYPES_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| typedef enum { | ||||
|   ST_ALIGN_START, | ||||
|   ST_ALIGN_MIDDLE, | ||||
|   ST_ALIGN_END | ||||
| } StAlign; | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_TYPES_H__ */ | ||||
							
								
								
									
										1382
									
								
								src/st/st-widget.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1382
									
								
								src/st/st-widget.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										117
									
								
								src/st/st-widget.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								src/st/st-widget.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
| /* | ||||
|  * st-widget.h: Base class for St 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(ST_H_INSIDE) && !defined(ST_COMPILATION) | ||||
| #error "Only <st/st.h> can be included directly.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef __ST_WIDGET_H__ | ||||
| #define __ST_WIDGET_H__ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <st/st-types.h> | ||||
| #include <st/st-theme.h> | ||||
| #include <st/st-theme-node.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define ST_TYPE_WIDGET                 (st_widget_get_type ()) | ||||
| #define ST_WIDGET(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_WIDGET, StWidget)) | ||||
| #define ST_IS_WIDGET(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_WIDGET)) | ||||
| #define ST_WIDGET_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_WIDGET, StWidgetClass)) | ||||
| #define ST_IS_WIDGET_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_WIDGET)) | ||||
| #define ST_WIDGET_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_WIDGET, StWidgetClass)) | ||||
|  | ||||
| typedef struct _StWidget               StWidget; | ||||
| typedef struct _StWidgetPrivate        StWidgetPrivate; | ||||
| typedef struct _StWidgetClass          StWidgetClass; | ||||
|  | ||||
| /** | ||||
|  * StWidget: | ||||
|  * | ||||
|  * Base class for stylable actors. The contents of the #StWidget | ||||
|  * structure are private and should only be accessed through the | ||||
|  * public API. | ||||
|  */ | ||||
| struct _StWidget | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActor parent_instance; | ||||
|  | ||||
|   StWidgetPrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * StWidgetClass: | ||||
|  * | ||||
|  * Base class for stylable actors. | ||||
|  */ | ||||
| struct _StWidgetClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActorClass parent_class; | ||||
|  | ||||
|   /* vfuncs */ | ||||
|   void (* draw_background) (StWidget *self); | ||||
|   void (* style_changed)   (StWidget *self); | ||||
| }; | ||||
|  | ||||
| GType st_widget_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| void                  st_widget_set_style_pseudo_class (StWidget    *actor, | ||||
|                                                         const gchar *pseudo_class); | ||||
| G_CONST_RETURN gchar *st_widget_get_style_pseudo_class (StWidget    *actor); | ||||
| void                  st_widget_set_style_class_name   (StWidget    *actor, | ||||
|                                                         const gchar *style_class); | ||||
| G_CONST_RETURN gchar *st_widget_get_style_class_name   (StWidget    *actor); | ||||
| void                  st_widget_set_style              (StWidget    *actor, | ||||
|                                                         const gchar *style); | ||||
| G_CONST_RETURN gchar *st_widget_get_style              (StWidget    *actor); | ||||
| void                  st_widget_set_theme              (StWidget    *actor, | ||||
|                                                         StTheme     *theme); | ||||
| StTheme *             st_widget_get_theme              (StWidget    *actor); | ||||
|  | ||||
| void         st_widget_set_has_tooltip  (StWidget    *widget, | ||||
|                                          gboolean     has_tooltip); | ||||
| gboolean     st_widget_get_has_tooltip  (StWidget    *widget); | ||||
| void         st_widget_set_tooltip_text (StWidget    *widget, | ||||
|                                          const gchar *text); | ||||
| const gchar* st_widget_get_tooltip_text (StWidget    *widget); | ||||
|  | ||||
| void st_widget_show_tooltip (StWidget *widget); | ||||
| void st_widget_hide_tooltip (StWidget *widget); | ||||
|  | ||||
| void st_widget_ensure_style (StWidget *widget); | ||||
|  | ||||
|  | ||||
| /* Only to be used by sub-classes of StWidget */ | ||||
| void          st_widget_style_changed        (StWidget  *widget); | ||||
| StThemeNode  *st_widget_get_theme_node       (StWidget  *widget); | ||||
|  | ||||
| ClutterActor *st_widget_get_background_image (StWidget  *actor); | ||||
| ClutterActor *st_widget_get_border_image     (StWidget  *actor); | ||||
| void          st_widget_draw_background      (StWidget  *widget); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __ST_WIDGET_H__ */ | ||||
							
								
								
									
										392
									
								
								src/st/test-theme.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										392
									
								
								src/st/test-theme.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,392 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include "st-theme.h" | ||||
| #include "st-theme-context.h" | ||||
| #include <math.h> | ||||
| #include <string.h> | ||||
|  | ||||
| static StThemeNode *root; | ||||
| static StThemeNode *group1; | ||||
| static StThemeNode *text1; | ||||
| static StThemeNode *text2; | ||||
| static StThemeNode *group2; | ||||
| static StThemeNode *text3; | ||||
| static StThemeNode *text4; | ||||
| static StThemeNode *group3; | ||||
| static StThemeNode *cairo_texture; | ||||
| static gboolean fail; | ||||
|  | ||||
| static const char *test; | ||||
|  | ||||
| static void | ||||
| assert_font (StThemeNode *node, | ||||
| 	     const char  *node_description, | ||||
| 	     const char  *expected) | ||||
| { | ||||
|   char *value = pango_font_description_to_string (st_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 (StTextDecoration decoration) | ||||
| { | ||||
|   GString *result = g_string_new (NULL); | ||||
|  | ||||
|   if (decoration & ST_TEXT_DECORATION_UNDERLINE) | ||||
|     g_string_append(result, " underline"); | ||||
|   if (decoration & ST_TEXT_DECORATION_OVERLINE) | ||||
|     g_string_append(result, " overline"); | ||||
|   if (decoration & ST_TEXT_DECORATION_LINE_THROUGH) | ||||
|     g_string_append(result, " line_through"); | ||||
|   if (decoration & ST_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 (StThemeNode     *node, | ||||
| 			const char      *node_description, | ||||
| 			StTextDecoration expected) | ||||
| { | ||||
|   StTextDecoration value = st_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 (StThemeNode *node, | ||||
| 			 const char  *node_description, | ||||
| 			 guint32      expected) | ||||
| { | ||||
|   ClutterColor color; | ||||
|   st_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 (StThemeNode *node, | ||||
| 			 const char  *node_description, | ||||
| 			 guint32      expected) | ||||
| { | ||||
|   ClutterColor color; | ||||
|   st_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 (StSide side) | ||||
| { | ||||
|   switch (side) | ||||
|     { | ||||
|     case ST_SIDE_TOP: | ||||
|       return "top"; | ||||
|     case ST_SIDE_RIGHT: | ||||
|       return "right"; | ||||
|     case ST_SIDE_BOTTOM: | ||||
|       return "bottom"; | ||||
|     case ST_SIDE_LEFT: | ||||
|       return "left"; | ||||
|     } | ||||
|  | ||||
|   return "<unknown>"; | ||||
| } | ||||
|  | ||||
| static void | ||||
| assert_border_color (StThemeNode *node, | ||||
|                      const char  *node_description, | ||||
|                      StSide       side, | ||||
|                      guint32      expected) | ||||
| { | ||||
|   ClutterColor color; | ||||
|   st_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 (StThemeNode *node, | ||||
| 			 const char  *node_description, | ||||
| 			 const char  *expected) | ||||
| { | ||||
|   const char *value = st_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., | ||||
| 		 st_theme_node_get_padding (group1, ST_SIDE_TOP)); | ||||
|   /* 12px == 12px */ | ||||
|   assert_length ("group1", "padding-right", 12., | ||||
| 		 st_theme_node_get_padding (group1, ST_SIDE_RIGHT)); | ||||
|   /* 2em == 32px (with a 12pt font) */ | ||||
|   assert_length ("group1", "padding-bottom", 32., | ||||
| 		 st_theme_node_get_padding (group1, ST_SIDE_BOTTOM)); | ||||
|   /* 1in == 72pt == 96px, at 96dpi */ | ||||
|   assert_length ("group1", "padding-left", 96., | ||||
| 		 st_theme_node_get_padding (group1, ST_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., | ||||
| 		 st_theme_node_get_padding (cairo_texture, ST_SIDE_TOP)); | ||||
|   /* From ClutterCairoTexture element selector */ | ||||
|   assert_length ("cairoTexture", "padding-right", 20., | ||||
| 		 st_theme_node_get_padding (cairo_texture, ST_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., | ||||
| 		 st_theme_node_get_padding (group2, ST_SIDE_TOP)); | ||||
|   assert_length ("group2", "padding-right", 2., | ||||
| 		 st_theme_node_get_padding (group2, ST_SIDE_RIGHT)); | ||||
|   assert_length ("group2", "padding-bottom", 3., | ||||
| 		 st_theme_node_get_padding (group2, ST_SIDE_BOTTOM)); | ||||
|   assert_length ("group2", "padding-left", 4., | ||||
| 		 st_theme_node_get_padding (group2, ST_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., | ||||
| 		 st_theme_node_get_border_width (group2, ST_SIDE_TOP)); | ||||
|   assert_length ("group2", "border-right-width", 2., | ||||
| 		 st_theme_node_get_border_width (group2, ST_SIDE_RIGHT)); | ||||
|   assert_length ("group2", "border-bottom-width", 5., | ||||
| 		 st_theme_node_get_border_width (group2, ST_SIDE_BOTTOM)); | ||||
|   assert_length ("group2", "border-left-width", 2., | ||||
| 		 st_theme_node_get_border_width (group2, ST_SIDE_LEFT)); | ||||
|  | ||||
|   assert_border_color (group2, "group2", ST_SIDE_TOP,    0x000000ff); | ||||
|   assert_border_color (group2, "group2", ST_SIDE_RIGHT,  0x000000ff); | ||||
|   assert_border_color (group2, "group2", ST_SIDE_BOTTOM, 0x0000ffff); | ||||
|   assert_border_color (group2, "group2", ST_SIDE_LEFT,   0x000000ff); | ||||
|  | ||||
|   assert_length ("group2", "border-radius-topleft", 10., | ||||
| 		 st_theme_node_get_border_radius (group2, ST_CORNER_TOPLEFT)); | ||||
|   assert_length ("group2", "border-radius-topright", 10., | ||||
| 		 st_theme_node_get_border_radius (group2, ST_CORNER_TOPRIGHT)); | ||||
|   assert_length ("group2", "border-radius-bottomright", 0., | ||||
| 		 st_theme_node_get_border_radius (group2, ST_CORNER_BOTTOMRIGHT)); | ||||
|   assert_length ("group2", "border-radius-bottomleft", 0., | ||||
| 		 st_theme_node_get_border_radius (group2, ST_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", "st/some-background.png"); | ||||
|   /* text1 inherits the background image but not the color */ | ||||
|   assert_background_color (text1,  "text1",  0x00000000); | ||||
|   assert_background_image (text1,  "text1",  "st/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", "st/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",  ST_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., | ||||
|                  st_theme_node_get_padding (text3, ST_SIDE_BOTTOM)); | ||||
| } | ||||
|  | ||||
| int | ||||
| main (int argc, char **argv) | ||||
| { | ||||
|   StTheme *theme; | ||||
|   StThemeContext *context; | ||||
|  | ||||
|   clutter_init (&argc, &argv); | ||||
|  | ||||
|   theme = st_theme_new ("st/test-theme.css", | ||||
|                         NULL, NULL); | ||||
|  | ||||
|   context = st_theme_context_new (); | ||||
|   st_theme_context_set_theme (context, theme); | ||||
|   st_theme_context_set_resolution (context, 96.); | ||||
|   st_theme_context_set_font (context, | ||||
| 				pango_font_description_from_string ("sans-serif 12")); | ||||
|  | ||||
|   root = st_theme_context_get_root_node (context); | ||||
|   group1 = st_theme_node_new (context, root, NULL, | ||||
|                               CLUTTER_TYPE_GROUP, "group1", NULL, NULL, NULL); | ||||
|   text1 = st_theme_node_new  (context, group1, NULL, | ||||
|                               CLUTTER_TYPE_TEXT, "text1", "special-text", NULL, NULL); | ||||
|   text2 = st_theme_node_new  (context, group1, NULL, | ||||
|                               CLUTTER_TYPE_TEXT, "text2", NULL, NULL, NULL); | ||||
|   group2 = st_theme_node_new (context, root, NULL, | ||||
|                               CLUTTER_TYPE_GROUP, "group2", NULL, NULL, NULL); | ||||
|   text3 = st_theme_node_new  (context, group2, NULL, | ||||
|                               CLUTTER_TYPE_TEXT, "text3", NULL, NULL, | ||||
|                               "color: #0000ff; padding-bottom: 12px;"); | ||||
|   text4 = st_theme_node_new  (context, group2, NULL, | ||||
|                               CLUTTER_TYPE_TEXT, "text4", NULL, "visited hover", NULL); | ||||
|   group3 = st_theme_node_new (context, group2, NULL, | ||||
|                               CLUTTER_TYPE_GROUP, "group3", NULL, "hover", NULL); | ||||
|   cairo_texture = st_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/st/test-theme.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								src/st/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 $@ | ||||
							
								
								
									
										64
									
								
								tests/interactive/borders.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								tests/interactive/borders.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const UI = imports.testcommon.ui; | ||||
|  | ||||
| UI.init(); | ||||
| let stage = Clutter.Stage.get_default(); | ||||
| stage.width = 600; | ||||
| stage.height = 700; | ||||
|  | ||||
| let vbox = new St.BoxLayout({ vertical: true, | ||||
|                               width: stage.width, | ||||
|                               height: stage.height, | ||||
|                               style: 'padding: 10px;' | ||||
|                                      + 'spacing: 20px;' | ||||
|                                      + 'background: #ffee88;' }); | ||||
| stage.add_actor(vbox); | ||||
|  | ||||
| vbox.add(new St.Label({ text: "Hello World", | ||||
|                         style: 'border: 1px solid black; ' | ||||
|                                + 'padding: 5px;' })); | ||||
|  | ||||
| vbox.add(new St.Label({ text: "Hello Round World", | ||||
|                         style: 'border: 3px solid green; ' | ||||
|                                + 'border-radius: 8px; ' | ||||
|                                + 'padding: 5px;' })); | ||||
|  | ||||
| vbox.add(new St.Label({ text: "Hello Background", | ||||
|                         style: 'border: 3px solid green; ' | ||||
|                                + 'border-radius: 8px; ' | ||||
|                                + 'background: white; ' | ||||
|                                + 'padding: 5px;' })); | ||||
|  | ||||
| vbox.add(new St.Label({ text: "Border, Padding, Content: 20px" })); | ||||
|  | ||||
| let b1 = new St.BoxLayout({ vertical: true, | ||||
|                             style: 'border: 20px solid black; ' | ||||
|                                    + 'background: white; ' | ||||
|                                    + 'padding: 20px;' }); | ||||
| vbox.add(b1); | ||||
|  | ||||
| b1.add(new St.BoxLayout({ width: 20, height: 20, | ||||
|                           style: 'background: black' })); | ||||
|  | ||||
| vbox.add(new St.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 St.Label({ text: "Transparent border", | ||||
|                         style: 'border: 20px solid transparent; ' | ||||
|                                + 'background: white; ' | ||||
|                                + 'padding: 10px;' })); | ||||
|  | ||||
| vbox.add(new St.Label({ text: "Border Image", | ||||
|                         style_class: "border-image", | ||||
|                         style: "padding: 10px;" })); | ||||
|  | ||||
| stage.show(); | ||||
| Clutter.main(); | ||||
| stage.destroy(); | ||||
							
								
								
									
										86
									
								
								tests/interactive/box-layout.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								tests/interactive/box-layout.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const UI = imports.testcommon.ui; | ||||
|  | ||||
| UI.init(); | ||||
| let stage = Clutter.Stage.get_default(); | ||||
|  | ||||
| let vbox = new St.BoxLayout({ vertical: true, | ||||
|                               width: stage.width, | ||||
|                               height: stage.height, | ||||
|                               style: 'padding: 10px;' | ||||
|                                      + 'spacing: 10px;' }); | ||||
| stage.add_actor(vbox); | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| let colored_boxes = new St.BoxLayout({ vertical: true, | ||||
|                                        width:  200, | ||||
|                                        height: 200, | ||||
|                                        style: 'border: 2px solid black;' }); | ||||
| vbox.add(colored_boxes, { x_fill: false, | ||||
|                           x_align: St.Align.MIDDLE }); | ||||
|  | ||||
| let b2 = new St.BoxLayout({ style: 'border: 2px solid #666666' }); | ||||
| colored_boxes.add(b2, { expand: true }); | ||||
|  | ||||
| b2.add(new St.Label({ text: "Expand", | ||||
|                       style: 'border: 1px solid #aaaaaa; ' | ||||
|                              + 'background: #ffeecc' }), | ||||
|        { expand: true }); | ||||
| b2.add(new St.Label({ text: "Expand\nNo Fill", | ||||
|                       style: 'border: 1px solid #aaaaaa; ' | ||||
|                              + 'background: #ccffaa' }), | ||||
|        { expand: true, | ||||
|          x_fill: false, | ||||
|          x_align: St.Align.MIDDLE, | ||||
|          y_fill: false, | ||||
|          y_align: St.Align.MIDDLE }); | ||||
|  | ||||
| colored_boxes.add(new St.Label({ text: "Default", | ||||
|                                  style: 'border: 1px solid #aaaaaa; ' | ||||
|                                         + 'background: #cceeff' })); | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| function createCollapsableBox(width) { | ||||
|     let b = new St.BoxLayout({ width: width, | ||||
|                                style: 'border: 1px solid black;' | ||||
|                                       + 'font: 13px Sans;' }); | ||||
|     b.add(new St.Label({ text: "Very Very Very Long", | ||||
|                          style: 'background: #ffaacc;' | ||||
|                                 + 'padding: 5px; ' | ||||
|                                 + 'border: 1px solid #666666;' }), | ||||
|           { expand: true }); | ||||
|     b.add(new St.Label({ text: "Very Very Long", | ||||
|                          style: 'background: #ffeecc; ' | ||||
|                                 + 'padding: 5px; ' | ||||
|                                 + 'border: 1px solid #666666;' }), | ||||
|           { expand: true }); | ||||
|     b.add(new St.Label({ text: "Very Long", | ||||
|                          style: 'background: #ccffaa; ' | ||||
|                                 + 'padding: 5px; ' | ||||
|                                 + 'border: 1px solid #666666;' }), | ||||
|           { expand: true }); | ||||
|     b.add(new St.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: St.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 St = imports.gi.St; | ||||
|  | ||||
| const UI = imports.testcommon.ui; | ||||
|  | ||||
| UI.init(); | ||||
| let stage = Clutter.Stage.get_default(); | ||||
|  | ||||
| let b = new St.BoxLayout({ vertical: true, | ||||
|                            width: stage.width, | ||||
|                            height: stage.height }); | ||||
| stage.add_actor(b); | ||||
|  | ||||
| let t; | ||||
|  | ||||
| t = new St.Label({ "text": "Bold", style_class: "bold" }); | ||||
| b.add(t); | ||||
| t = new St.Label({ "text": "Monospace", style_class: "monospace" }); | ||||
| b.add(t); | ||||
| t = new St.Label({ "text": "Italic", style_class: "italic" }); | ||||
| b.add(t); | ||||
| t = new St.Label({ "text": "Bold Italic", style_class: "bold italic" }); | ||||
| b.add(t); | ||||
| t = new St.Label({ "text": "Big Italic", style_class: "big italic" }); | ||||
| b.add(t); | ||||
| t = new St.Label({ "text": "Big Bold", style_class: "big bold" }); | ||||
| b.add(t); | ||||
|  | ||||
| let b2 = new St.BoxLayout({ vertical: true, style_class: "monospace" }); | ||||
| b.add(b2); | ||||
| t = new St.Label({ "text": "Big Monospace", style_class: "big" }); | ||||
| b2.add(t); | ||||
| t = new St.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 St = imports.gi.St; | ||||
|  | ||||
| const UI = imports.testcommon.ui; | ||||
|  | ||||
| UI.init(); | ||||
| let stage = Clutter.Stage.get_default(); | ||||
|  | ||||
| let vbox = new St.BoxLayout({ vertical: true, | ||||
|                               width: stage.width, | ||||
|                               height: stage.height }); | ||||
| stage.add_actor(vbox); | ||||
|  | ||||
| let hbox = new St.BoxLayout({ style: 'spacing: 12px;' }); | ||||
| vbox.add(hbox); | ||||
|  | ||||
| let text = new St.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 St.Button ({ label: 'Smaller', style_class: 'push-button' }); | ||||
| hbox.add (button); | ||||
| button.connect('clicked', function() { | ||||
|                    size /= 1.2; | ||||
|                    update_size (); | ||||
|                }); | ||||
|  | ||||
| button = new St.Button ({ label: 'Bigger', style_class: 'push-button' }); | ||||
| 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 St = imports.gi.St; | ||||
|  | ||||
| const UI = imports.testcommon.ui; | ||||
|  | ||||
| UI.init(); | ||||
| let stage = Clutter.Stage.get_default(); | ||||
|  | ||||
| let vbox = new St.BoxLayout({ vertical: true, | ||||
|                               width: stage.width, | ||||
|                               height: stage.height, | ||||
|                               style: "padding: 10px;" }); | ||||
| stage.add_actor(vbox); | ||||
|  | ||||
| let v = new St.ScrollView(); | ||||
| vbox.add(v, { expand: true }); | ||||
|  | ||||
| let b = new St.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 St.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(); | ||||
							
								
								
									
										56
									
								
								tests/interactive/table.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								tests/interactive/table.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const UI = imports.testcommon.ui; | ||||
|  | ||||
| UI.init(); | ||||
| let stage = Clutter.Stage.get_default(); | ||||
| stage.width = stage.height = 600; | ||||
|  | ||||
| let vbox = new St.BoxLayout({ vertical: true, | ||||
|                               width: stage.width, | ||||
|                               height: stage.height, | ||||
|                               style: 'padding: 10px; ' | ||||
|                                      + 'spacing: 10px;' | ||||
|                                      + 'font: 15px sans-serif;' }); | ||||
| stage.add_actor(vbox); | ||||
|  | ||||
| function L(text, color) { | ||||
|     return new St.Label({ text: text, | ||||
|                           style: "background: " + color + ";" | ||||
|                                  + "border: 1px solid rgba(0,0,0,0.5);" | ||||
|                                  + "padding: 1em;" }); | ||||
| } | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| let table = new St.Table({ style: "border: 10px solid #888888;" | ||||
|                                   + "padding: 10px;" | ||||
|                                   + "spacing-rows: 5px;" | ||||
|                                   + "spacing-columns: 15px;" }); | ||||
| vbox.add(table, { expand: true }); | ||||
|  | ||||
| table.add(L("1", "#ff0000"), | ||||
|           { row: 0, col: 0, col_span: 3 }); | ||||
| table.add(L("2", "#00ff00"), | ||||
|           { row: 1, col: 0, row_span: 2 }); | ||||
| table.add(L("3", "#0000ff"), | ||||
|           { row: 1, col: 1, | ||||
|             x_expand: 0 }); | ||||
| table.add(L("4", "#ffff00"), | ||||
|           { row: 1, col: 2, | ||||
|             y_expand: 0, y_fill: 0 | ||||
|           }); | ||||
| table.add(L("5", "#ff00ff"), | ||||
|           { row: 2, col: 1, x_expand: 0 }); | ||||
| table.add(L("6", "#00ffff"), | ||||
|           { row: 2, col: 2, | ||||
|             x_expand: 0, x_fill: 0, x_align: 1.0, | ||||
|             y_expand: 0, y_fill: 0, y_align: 1.0 }); | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| stage.show(); | ||||
| Clutter.main(); | ||||
							
								
								
									
										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; | ||||
| } | ||||
|  | ||||
| .push-button { | ||||
|     background: #eeddbb; | ||||
|     border: 1px solid black; | ||||
|     border-radius: 8px; | ||||
|     padding: 5px; | ||||
| } | ||||
|  | ||||
| .push-button:hover { | ||||
|     background: #ffeecc; | ||||
| } | ||||
|  | ||||
| .push-button: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 St = imports.gi.St; | ||||
| 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 = St.ThemeContext.get_for_stage (stage); | ||||
|     let stylesheetPath = GLib.getenv("GNOME_SHELL_TESTSDIR") + "/testcommon/test.css"; | ||||
|     let theme = new St.Theme ({ application_stylesheet: stylesheetPath }); | ||||
|     context.set_theme (theme); | ||||
| } | ||||
| @@ -7,6 +7,8 @@ | ||||
|       href="git://git.clutter-project.org/"/> | ||||
|   <repository type="git" name="git.gnome.org" | ||||
|       href="git://git.gnome.org/"/> | ||||
|   <repository type="git" name="git.moblin.org" | ||||
|       href="git://git.moblin.org"/> | ||||
|  | ||||
|   <autotools id="gobject-introspection"> | ||||
|     <branch repo="git.gnome.org" module="gobject-introspection"/> | ||||
| @@ -36,6 +38,13 @@ | ||||
|     </dependencies> | ||||
|   </autotools> | ||||
|  | ||||
|   <autotools id="clutter-imcontext"> | ||||
|     <branch repo="git.moblin.org" module="clutter-imcontext"/> | ||||
|     <dependencies> | ||||
|         <dep package="clutter"/> | ||||
|     </dependencies> | ||||
|   </autotools> | ||||
|  | ||||
|   <autotools id="gconf" autogenargs="--disable-defaults-service"> | ||||
|     <branch repo="git.gnome.org" module="gconf"/> | ||||
|   </autotools> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user