Index: /CKEditor/branches/prototype/_source/core/tools.js
===================================================================
--- /CKEditor/branches/prototype/_source/core/tools.js	(revision 2571)
+++ /CKEditor/branches/prototype/_source/core/tools.js	(revision 2572)
@@ -21,5 +21,5 @@
 
 /**
- * @fileOverview Defines the {@link CKEDITOR.tools} object, which constains
+ * @fileOverview Defines the {@link CKEDITOR.tools} object, which contains
  *		utility functions.
  */
Index: /CKEditor/branches/prototype/_source/plugins/dialog/plugin.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/dialog/plugin.js	(revision 2571)
+++ /CKEditor/branches/prototype/_source/plugins/dialog/plugin.js	(revision 2572)
@@ -53,9 +53,9 @@
 		return;
 	}
+	definition = new CKEDITOR.dialog._.definitionObject( this, definition );
+	definition = CKEDITOR.fire( 'dialogDefinition', { name : dialogName, definition : definition }, editor ).definition;
 
 	// Initialize some basic parameters.
-	if ( !this._ )
-		this._ = {};
-	CKEDITOR.tools.extend( this._, {
+	CKEDITOR.tools.extend( ( this._ || ( this._ = {} ) ), {
 			editor : editor,
 			element : editor.theme.buildDialog( editor ),
@@ -68,5 +68,5 @@
 	// Initialize the parts map.
 	var element = this._.element.getFirst(),
-		i;
+		i, me = this;
 	this._.parts = {
 		'tl' : [0,0],
@@ -119,26 +119,42 @@
 				}, this, null, 0);
 
+	var iterContents = function( func )
+	{
+		var breakFlag = false;
+		for ( var i in me._.contents )
+		{
+			for ( var j in me._.contents[i] )
+			{
+				breakFlag = func.call( this, me._.contents[i][j] );
+				if ( breakFlag )
+					break;
+			}
+			if ( breakFlag )
+				break;
+		}
+	}
+
 	this.on( 'ok', function( evt )
 			{
-				for ( var i in this._.contents )
-				{
-					if ( this._.contents[i].validate && !this._.contents[i].validate( this ) )
+				iterContents( function( item )
 					{
-						evt.data.hide = false;
-						break;
-					}
-				}
+						if ( item.validate && !item.validate( this ) )
+						{
+							evt.data.hide = false;
+							return true;
+						}
+					});
 			}, this, null, 0 );
 	this.on( 'cancel', function( evt )
 			{
-				for ( var i in this._.contents )
-				{
-					if ( this._.contents[i].isChanged() )
+				iterContents( function( item )
 					{
-						if ( !confirm( 'Some of the options have been changed. Are you sure to close the dialog?' ) )
-							evt.data.hide = false;
-						break;
-					}
-				}
+						if ( item.isChanged() )
+						{
+							if ( !confirm( 'Some of the options have been changed. Are you sure to close the dialog?' ) )
+								evt.data.hide = false;
+							return true;
+						}
+					});
 			}, this, null, 0 );
 
@@ -289,9 +305,10 @@
 		// Reset all inputs back to their default value.
 		for ( var i in this._.contents )
-		{
-			var c = this._.contents[i];
-			if ( c.reset )
-				c.reset();
-		}
+			for ( var j in this._.contents[i] )
+			{
+				var c = this._.contents[i][j];
+				if ( c.reset )
+					c.reset();
+			}
 
 		// Set z-index.
@@ -344,5 +361,5 @@
 	},
 
-	addPage : function( contents, index )
+	addPage : function( contents )
 	{
 		var pageHtml = [],
@@ -350,13 +367,13 @@
 			tab,
 			titleHtml = contents.title ? 'title="' + CKEDITOR.tools.htmlEncode( contents.title ) + '" ' : '',
-			elements = contents.elements;
-
-		CKEDITOR.dialog._.uiElementBuilders.vbox.build( this,
-				{
-					type : 'vbox',
-					className : 'cke_dialog_page_contents',
-					children : contents.elements
-				}, pageHtml );
-
+			elements = contents.elements,
+			vbox = CKEDITOR.dialog._.uiElementBuilders.vbox.build( this,
+					{
+						type : 'vbox',
+						className : 'cke_dialog_page_contents',
+						children : contents.elements
+					}, pageHtml );
+
+		// Create the HTML for the tab and the content block.
 		page = CKEDITOR.dom.element.createFromHtml( pageHtml.join( '' ) );
 		tab = CKEDITOR.dom.element.createFromHtml( [
@@ -369,5 +386,18 @@
 				'</div></span>'
 			].join( '' ) );
+
+		// Take records for the tabs and elements created.
 		this._.tabs[ contents.id ] = [ tab, page ];
+		var contentMap = this._.contents[ contents.id ] = {},
+			cursor,
+			children = vbox.getChild();
+		while ( ( cursor = children.shift() ) )
+		{
+			contentMap[ cursor.id ] = cursor;
+			if ( typeof( cursor.getChild ) == 'function' )
+				children.push.apply( children, cursor.getChild() );
+		}
+
+		// Attach the DOM nodes.
 		tab.getFirst().unselectable();
 		page.appendTo( this._.parts.contents );
@@ -428,17 +458,17 @@
 	},
 
-	getChild : function( id )
-	{
-		return this._.contents[id];
-	},
-
-	getValueOf : function( id )
-	{
-		return this._.contents[id] && this._.contents[id].getValue();
-	},
-
-	setValueOf : function( id, value )
-	{
-		return this._.contents[id] && this._.contents[id].setValue( value );
+	getChild : function( pageId, elementId )
+	{
+		return this._.contents[pageId][elementId];
+	},
+
+	getValueOf : function( pageId, elementId )
+	{
+		return this.getChild( pageId, elementId ).getValue();
+	},
+
+	setValueOf : function( pageId, elementId, value )
+	{
+		return this.getChild( pageId, elementId ).setValue( value );
 	}
 };
@@ -481,6 +511,4 @@
 			this._.uiElementBuilders[typeName] = builder;
 		},
-
-		storedDialogs : {},
 
 		setMargins : function( top, right, bottom, left )
@@ -802,6 +830,168 @@
 
 	currentZIndex : null,
-
-	margins : [0, 0, 0, 0]
+	
+	storedDialogs : {},
+
+	margins : [0, 0, 0, 0],
+
+	definitionObject : function( dialog, dialogDefinition )
+	{
+		if ( arguments.length < 2 )
+			return;
+		( this._ || ( this._ = {} ) ).dialog = dialog;
+		CKEDITOR.tools.extend( this, dialogDefinition );
+
+		var cursor, i;
+		for ( i = 0 ; i < dialogDefinition.contents.length && ( cursor = dialogDefinition.contents[i] ) ; i++ )
+			dialogDefinition.contents[i] = new CKEDITOR.dialog._.contentObject( dialog, cursor.id, cursor );
+		for ( i = 0 ; i < dialogDefinition.buttons.length && ( cursor = dialogDefinition.buttons[i] ) ; i++ )
+			dialogDefinition.buttons[i] = new CKEDITOR.dialog._.buttonObject( dialog, cursor );
+	},
+
+	contentObject : function( dialog, id, contentDefinition )
+	{
+		if ( arguments.length < 3 )
+			return;
+		CKEDITOR.tools.extend( ( this._ || ( this._ = {} ) ),
+				{
+					id : id,
+					dialog : dialog
+				});
+		CKEDITOR.tools.extend( this, contentDefinition );
+	},
+
+	buttonObject : function( dialog, buttonDefinition )
+	{
+		( this._ || ( this._ = {} ) ).dialog = dialog;
+		CKEDITOR.tools.extend( this, buttonDefinition );
+	}
+};
+
+CKEDITOR.dialog._.definitionObject.prototype = 
+{
+	getContents : function( id )
+	{
+		for ( var i = 0, cursor ; i < this.contents.length && ( cursor = this.contents[i] ) ; i++ )
+		{
+			if ( cursor.id == id )
+				return cursor;
+		}
+		return null;
+	},
+
+	getButton : function( id )
+	{
+		for ( var i = 0, cursor ; i < this.buttons.length && ( cursor = this.buttons[i] ) ; i++ )
+		{
+			if ( cursor.id == id )
+				return cursor;
+		}
+		return null;
+	},
+
+	addContents : function( contentDefinition, nextSiblingId )
+	{
+		for ( var i = 0, cursor ; i < this.contents.length && ( cursor = this.contents[i] ) ; i++ )
+		{
+			if ( cursor.id == nextSiblingId )
+			{
+				this.contents.splice( i, 0, contentDefinition );
+				return contentDefinition;
+			}
+		}
+		this.contents.push( contentDefinition );
+		return contentDefinition;
+	},
+
+	addButton : function( buttonDefinition, nextSiblingId )
+	{
+		for ( var i = 0, cursor ; i < this.buttons.length && ( cursor = this.buttons[i] ) ; i++ )
+		{
+			if ( cursor.id == nextSiblingId )
+			{
+				this.buttons.splice( i, 0, buttonDefinition );
+				return buttonDefinition;
+			}
+		}
+		this.buttons.push( buttonDefinition );
+		return buttonDefinition;
+	},
+
+	removeContents : function( id )
+	{
+		for ( var i = 0; i < this.contents.length ; i++ )
+		{
+			if ( this.contents[i].id == id )
+				return this.contents.splice( i, 1 );
+		}
+		return null;
+	},
+
+	removeButton : function( id )
+	{
+		for ( var i = 0 ; i < this.buttons.length ; i++ )
+		{
+			if ( this.buttons[i].id == id )
+				return this.buttons.splice( i, 1 );
+		}
+		return null;
+	}
+};
+
+CKEDITOR.dialog._.contentObject.prototype = 
+{
+	activate : function()
+	{
+		this._.dialog.selectPage( this._.id );
+	},
+
+	get : function( id )
+	{
+		for ( var i = 0, cursor ; i < this.elements.length && ( cursor = this.elements[i] ) ; i++ )
+		{
+			if ( cursor.id == id )
+				return cursor;
+		}
+		return null;
+	},
+
+	add : function( elementDefinition, nextSiblingId )
+	{
+		for ( var i = 0, cursor ; i < this.elements.length && ( cursor = this.elements[i] ) ; i++ )
+		{
+			if ( cursor.id == nextSiblingId )
+			{
+				this.elements.splice( i, 0, elementDefinition );
+				return elementDefinition;
+			}
+		}
+		this.elements.push( elementDefinition );
+		return elementDefinition;
+	},
+
+	remove : function( id )
+	{
+		for ( var i = 0 ; i < this.elements.length ; i++ )
+		{
+			if ( this.elements[i].id == id )
+				return this.elements.splice( i, 1 );
+		}
+		return null;
+	}
+};
+
+CKEDITOR.dialog._.buttonObject.prototype =
+{
+	click : function()
+	{
+	},
+
+	enable : function()
+	{
+	},
+
+	disable : function()
+	{
+	}
 };
 
@@ -823,5 +1013,4 @@
 		// Set the id, a unique id is required for getElement() to work.
 		attributes.id = id;
-		dialog._.contents[id] = this;
 
 		// Set the type and definition CSS class names.
@@ -880,6 +1069,5 @@
 			return;
 
-		if ( !this._ )
-			this._ = {};
+		this._ || ( this._ = {} );
 
 		var children = this._.children = childObjList,
@@ -923,6 +1111,5 @@
 			return;
 
-		if ( !this._ )
-			this._ = {};
+		this._ || ( this._ = {} );
 
 		var children = this._.children = childObjList,
@@ -990,6 +1177,13 @@
 		getChild : function( indices )
 		{
+			// If no arguments, return a clone of the children array.
+			if ( arguments.length < 1 )
+				return this._.children.concat();
+
+			// If indices isn't array, make it one.
 			if ( !indices.splice )
 				indices = [ indices ];
+
+			// Retrieve the child element according to tree position.
 			if ( indices.length < 2 )
 				return this._.children[ indices[0] ];
@@ -1012,6 +1206,6 @@
 			if ( typeof( CKEDITOR.dialog._.dialogDefinitions[dialogName] ) == 'function' )
 			{
-				var dialog = CKEDITOR.dialog.storedDialogs[dialogName] || new CKEDITOR.dialog( this, dialogName );
-				CKEDITOR.dialog.storedDialogs[dialogName] = dialog;
+				var dialog = CKEDITOR.dialog._.storedDialogs[dialogName] || new CKEDITOR.dialog( this, dialogName );
+				CKEDITOR.dialog._.storedDialogs[dialogName] = dialog;
 				dialog.show();
 				return dialog;
Index: /CKEditor/branches/prototype/_source/plugins/dialogui/plugin.js
===================================================================
--- /CKEditor/branches/prototype/_source/plugins/dialogui/plugin.js	(revision 2571)
+++ /CKEditor/branches/prototype/_source/plugins/dialogui/plugin.js	(revision 2572)
@@ -25,6 +25,5 @@
 	var initPrivateObject = function( elementDefinition )
 	{
-		if ( !this._ )
-			this._ = {};
+		this._ || ( this._ = {} );
 		if ( 'default' in elementDefinition )
 			this._['default'] = elementDefinition['default'];
