/* Copyright (c) 2011, Geert Bergman (geert@scrivo.nl)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of "Scrivo" nor the names of its contributors may be
 *    used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: Calendar.js 616 2013-04-22 23:48:38Z geert $
 */

"use strict";

SUI.dialog.Calendar = SUI.defineClass(
	/** @lends SUI.dialog.Calendar.prototype */{

	/** @ignore */ baseClass: SUI.dialog.OKCancelDialog,

	/**
	 * @class
	 * SUI.dialog.Calendar is a class to display a date/time dialog. Depending
	 * of the given arguments a date, time or datetime selection box is shown.
	 *
	 * @augments SUI.dialog.OKCancelDialog
	 *
	 * @description
	 * Show a modal dialog for date and/or time selection.
	 *
	 * @constructs
	 * @param see base class
	 * @param {boolean} arg.iso Use the ISO 8601 week day system
	 *     (true/default) or or the American (false) style
	 * @param {Date} arg.date Initial date selection
	 * @param {String} arg.type Type of the dialog "time", "date" (default)
	 *     or "datetime"
	 */
	initializer: function(arg) {

		SUI.dialog.Calendar.initializeBase(this, arg);

		// use iso unless told not to
		this.iso = arg.iso === undefined ? true : arg.iso;

		// get the initial date
		this._selDate = arg.date || new Date();

		// display the calendar for the selected month and year
		this._monthYear = this._selDate;

		// should we need draw a date or time box or both
		if (arg.type == "datetime") {
			this._type = 3;
		} else if (arg.type == "time") {
			this._type = 1;
		} else {
			this._type = 2;
		}

		// set the appropriate caption
		var t = SUI.i18n.captionDate;
		if (this._type ==- 3) {
			t = SUI.i18n.captionDatetime;
		} else if (this._type == 1) {
			t = SUI.i18n.captionTime;
		}
		this.caption(t);

		// if we have a date box also initialize the date scrolling actions
		if (this._type & 2) {
		 this._initCalendarActions();
		}
	},

	/**
	 * Border width of borders around cells
	 */
	BORDER_WIDTH: 1,

	/**
	 * (Standard) width of the calendar cells (including margin)
	 */
	BOX_WIDTH: 26,

	/**
	 * (Standard) height of the calendar cells (including margin)
	 */
	BOX_HEIGHT: 20,

	/**
	 * Margin between cells
	 */
	BOX_MARGIN: 2,

	/**
	 * Size of the date navigation buttons
	 */
	BUTTON_SIZE: 22,

	/**
	 * A little extra margin around the month calendar to give more space to
	 * the navigation bar
	 */
	BUTTON_EXTRA_SIDE_MARGIN: 1,

	/**
	 * Margin of the month calendar
	 */
	DATE_MARGIN: 7,

	/**
	 * Height of the date navigation bar or the time header
	 */
	HEADER_HEIGHT: 23,

	/**
	 * Top of text in the header
	 */
	HEADER_TEXT_TOP: 3,

	/**
	 * fraction to calculate width for the month and year scrollers
	 */
	HEADER_SPLIT_AT: .533,

	/**
	 * Width of the margin between the date and time box
	 */
	SPLIT_MARGIN: 10,

	/**
	 * Side margins of the time box (when there is no date box)
	 */
	TIME_SIDE_MARGIN: 24,

	/**
	 * Bottom margin of the time box
	 */
	TIME_BOTTOM_MARGIN: 5,

	/**
	 * Top margin of the date an time boxes
	 */
	TOP_MARGIN: 1,

	/**
	 * Return the form's selected value
	 */
	formToData: function() {
		this.close();
	 return this._selDate;
	},

	/**
	 * Show the calendar dialog centered on the screen
	 */
	show: function() {
		this._drawCalendar();
		this._setDialogSize();
		this.center();
		SUI.dialog.Calendar.parentMethod(this, "show");
	},

	// reference to the box with the date selector
	_dateBox: null,

	// month and year of the currently displayed calendar page
	_mohthYear: null,

	// currently selected date
	_selDate: null,

	// reference to the box with the time selector
	_timeBox: null,

	// binary selector 1 time, 2 date, 3 datetime
	_type: true,

	// add a CSS mouseover hover on a calender cell
	_addHovers: function(cell) {
	 // set a CSS class on mouseover
		SUI.browser.addEventListener(cell.el(), "mouseover",
		 function(e) {
				if (!cell.addClass("sui-cal-day-hover")) {
					SUI.browser.noPropagation(e);
				}
			}
		);
	 // remove a CSS class on mouseout
		SUI.browser.addEventListener(cell.el(), "mouseout",
		 function(e) {
			 if (!cell.removeClass("sui-cal-day-hover")) {
			   SUI.browser.noPropagation(e);
			 }
		 }
		);
	},

	// set the _selectDate handler to the onclick of a cell
	_addSelectDate: function(cell, val) {
	 var that = this;
		SUI.browser.addEventListener(cell.el(), "click",
		 function(e) {
		   if (!that._selectDate(val)) {
			  SUI.browser.noPropagation(e);
		   }
			}
		);
	},

	// set the _selectHour handler to the onclick of a cell
	_addSelectHour: function(cell, val) {
	 var that = this;
		SUI.browser.addEventListener(cell.el(), "click",
		 function(e) {
		   if (!that._selectHour(val)) {
			  SUI.browser.noPropagation(e);
		   }
			}
		);
	},

	// set the _selectMinutes handler to the onclick of a cell
	_addSelectMinutes: function(cell, val) {
	 var that = this;
		SUI.browser.addEventListener(cell.el(), "click",
		 function(e) {
		   if (!that._selectMinutes(val)) {
			  SUI.browser.noPropagation(e);
		   }
			}
		);
	},

	// construct a date calendar box in which the user can select a date
	_buildDateBox: function() {

	 var date = this._monthYear;

		// create a new box for the month table
		var cont = new SUI.Box({
			width: 8 * this.BOX_WIDTH + this.BOX_MARGIN +
				2 * this.BUTTON_EXTRA_SIDE_MARGIN,
			height: this.HEADER_HEIGHT + 7 * this.BOX_HEIGHT +
				this.BUTTON_EXTRA_SIDE_MARGIN
		});

		// add the navigation header to the box
		this._drawDateNavigation(cont);

		// set top and left position for drawing the week-day headers
		var l = this.BUTTON_EXTRA_SIDE_MARGIN;
		var t = this.HEADER_HEIGHT-this.BOX_MARGIN;

		// start with the week number header
		var dv = new SUI.TextBox({
		 parent: cont,
		 text: SUI.i18n.weekShort,
		 top: t + this.BOX_MARGIN,
		 left: l + this.BOX_MARGIN,
		 width: this.BOX_WIDTH - this.BOX_MARGIN,
		 height: this.BOX_HEIGHT - this.BOX_MARGIN,
		 border: new SUI.Border(this.BORDER_WIDTH),
		 padding: new SUI.Padding(0, 0, 0, this.BOX_MARGIN)
	 });
		dv.addClass("sui-cal-header");
		dv.display();

		// move to the next column
		l += this.BOX_WIDTH;

		// now draw the week-day headers
		for (var i=0; i<SUI.i18n.arrDaysShort.length; i++) {

		 dv = new SUI.TextBox({
			 parent: cont,
				text: (this.iso) ? SUI.i18n.arrDaysShort[i]
					: SUI.i18n.arrDaysShort[i?i-1:6],
			 top: t + this.BOX_MARGIN,
			 left: l,
			 width: this.BOX_WIDTH,
			 height: this.BOX_HEIGHT - this.BOX_MARGIN,
			 border: new SUI.Border(this.BORDER_WIDTH),
			 padding: new SUI.Padding(0, 0, 0, this.BOX_MARGIN)
		 });
			dv.addClass("sui-cal-header");
			dv.display();

			// move to the next column
			l += this.BOX_WIDTH;
		}
		// move to the next row
		t += this.BOX_HEIGHT;

		this._drawMonthTable(cont, t, this.BUTTON_EXTRA_SIDE_MARGIN);

		return cont;
	},

	// construct a time table box in which the user can select a time
	_buildTimeBox: function(date) {

	 // create a box for the time table
		var cont = new SUI.Box({
		 width: 6 * this.BOX_WIDTH + this.BOX_MARGIN,
			height: 6 * this.BOX_HEIGHT + 2 * this.HEADER_HEIGHT
		});

		// create a box for the time table title
		var tm = new SUI.TextBox({
		 parent: cont,
		 top: this.HEADER_TEXT_TOP,
		 width: cont.width(),
		 height: this.HEADER_HEIGHT,
		 text: SUI.i18n.time
		});
		tm.el().style.textAlign = "center";

		// create a box for the table section of the time table
		var tt = new SUI.Box({
		 parent: cont,
		 top: this.HEADER_HEIGHT-this.BOX_MARGIN,
		 width: cont.width(),
		 height: this.BOX_HEIGHT*6
		});

		// draw the hours table
		this._drawHoursTable(tt);
		// draw the minutes table
		var selsecs = this._drawMinutesTable(tt, 4 * this.BOX_HEIGHT);

		// create a box for the the exact time row
		var et = new SUI.Box({
		 parent: cont,
		 top: 6 * this.BOX_HEIGHT + this.HEADER_HEIGHT,
		 left: 0,
		 width: cont.width()-this.BOX_MARGIN,
		 height: this.HEADER_HEIGHT
		});
		et.el().style.textAlign = "right";

		// the value for the minutes input field: don't use the multiples of 5
		var min = this._selDate.getMinutes();
		var v = (min % 5) ? min : "";

		// create a label for the input box
		var lbl = new SUI.form.Label({
		 title: SUI.i18n.exactMinutes+": ",
		 parent: et
		});
		lbl.el().style.position = "relative";

		// create the input box
		var inp = new SUI.form.Input({
		 width: this.BOX_WIDTH-2*this.BOX_MARGIN,
		 parent: et
		});
		inp.el().value = v;
		inp.el().style.position = "relative";

		// point the label to the input box
		lbl.forBox(inp);

		// set the handler to retrieve exact minutes input from the user
		var that = this;
		SUI.browser.addEventListener(inp.el(), "input",
		 function(e) {
			 if (!that._inputMinutes(inp.el().value, selsecs)) {
			   SUI.browser.noPropagation(e);
			 }
			}
		);

		// display the elements of the time table
		et.display();
		tt.display();
		tm.display();
		inp.display();

		return cont;
	},

	// draw the dialog content
	_drawCalendar: function() {

	 // if we need to draw a date box ...
		if (this._type & 2) {
		 // ... remove it if it was previously drawn
			if (this._dateBox) {
			 this._dateBox.removeBox();
			}
			// create a new date box
			this._dateBox = this._buildDateBox();
			this._dateBox.top(this.TOP_MARGIN);
			this._dateBox.left(this.DATE_MARGIN);
			this._dateBox.parent(this.clientPanel.clientBox());
			// and display it
			this._dateBox.display();
		}

	 // if we need to draw a time box ...
		if (this._type & 1) {
		 // ... remove it if it was previously drawn
			if (this._timeBox) {
				this._timeBox.removeBox();
			}
			// create a new time box
			this._timeBox = this._buildTimeBox();
			this._timeBox.top(this.TOP_MARGIN);
			// the left margin depends if there is a date box too
			this._timeBox.left(this._dateBox
				? this._dateBox.width() + this.DATE_MARGIN + this.SPLIT_MARGIN
			 : this.TIME_SIDE_MARGIN);
			this._timeBox.parent(this.clientPanel.clientBox());
			// and display it
			this._timeBox.display();
		}

	},

	// draw a bar with year and month scrollers and a button to go to the
	// current date
	_drawDateNavigation: function(cont) {

		// width of the navigation header
		var w = this.BOX_WIDTH * 8 + this.BOX_MARGIN +
			this.BUTTON_EXTRA_SIDE_MARGIN * 2;

		// object that holds the position of the toolbar buttons
		var pos = {
			"cal.prevm": 0,
			"cal.nextm": Math.ceil(w * this.HEADER_SPLIT_AT, 10) -
				this.BUTTON_SIZE,
			"cal.prevy": Math.ceil(w * this.HEADER_SPLIT_AT, 10),
			"cal.nexty": w - 2 * this.BUTTON_SIZE,
			"cal.today": w - this.BUTTON_SIZE
		};

		// set the positions and actions of the toolbar buttons
		for (var i in pos) {
			var b = new SUI.ToolbarButton({
				actionId: i,
			 left: pos[i],
				width: this.BUTTON_SIZE,
				height: this.BUTTON_SIZE
			});
			b.parent(cont);
			b.setAction(this._actionList);
			b.draw();
		}

		// create the month text box
		var m = new SUI.TextBox({
		 parent: cont,
		 text: SUI.i18n.arrMonths[this._monthYear.getMonth()],
			top: this.HEADER_TEXT_TOP,
		 left: this.BUTTON_SIZE,
			width: pos["cal.nextm"] - this.BUTTON_SIZE,
			height: this.HEADER_HEIGHT
		});
		m.el().style.textAlign = "center";
		m.display();

		// create the year text box
		var y = new SUI.TextBox({
		 parent: cont,
		 text: this._monthYear.getFullYear(),
			top: this.HEADER_TEXT_TOP,
		 left: pos["cal.prevy"] + this.BUTTON_SIZE,
			width: pos["cal.nexty"] - this.BUTTON_SIZE-pos["cal.prevy"],
			height: this.HEADER_HEIGHT
		});
		y.el().style.textAlign = "center";
		y.display();
	},

	// draw a table of 4 by 6 cells for the hours of the day
	_drawHoursTable: function(tt) {

		var l = 0;
		var t = 0;

		// 24 hours in 4 rows ...
		for (var i=0; i<4; i++) {
			l = 0;
			// ... of 6 cells
			for (var j=0; j<6; j++) {

			 // current hour
				var x = i*6+j;

				// get the style
				var st = "sui-cal-day";
				if (x == this._selDate.getHours() ) {
					st += " sui-cal-selected";
				}

				var dv = new SUI.TextBox({
				 parent: tt,
				 text: String(x),
				 top: t+this.BOX_MARGIN,
				 left: l+this.BOX_MARGIN,
				 width: this.BOX_WIDTH-this.BOX_MARGIN,
				 height: this.BOX_HEIGHT-this.BOX_MARGIN,
				 border: new SUI.Border(this.BORDER_WIDTH)
				});
				dv.addClass(st);
				dv.display();

				// add the event handlers (hover and onclick)
				this._addHovers(dv);
				this._addSelectHour(dv, x);

				// move to the next cell
				l += this.BOX_WIDTH;
			}
			// move to the next row
			t += this.BOX_HEIGHT;
		}

	},

	// draw a table of 2 by 6 cells for the minutes of the day
	_drawMinutesTable: function(tt, t) {

		var l = 0;
		var selsecs = null;

		// 12 increments of 5 minutes in 2 rows ...
		for (var i=0; i<2; i++) {
			l = 0;
			// ... of 6 cells
			for (var j=0; j<6; j++) {
			 // current minutes
				var x = (i*6+j)*5;
				// get the style
				var st = "sui-cal-weekend";
				if (x == this._selDate.getMinutes() ) {
					st += " sui-cal-selected";
				}
				// create zero padded variant of x
				var x1 = x<10 ? ":0"+x : ":"+x;

				var cm = new SUI.TextBox({
				 parent: tt,
				 text: x1,
				 top: t+this.BOX_MARGIN,
				 left: l+this.BOX_MARGIN,
				 width: this.BOX_WIDTH-this.BOX_MARGIN,
				 height: this.BOX_HEIGHT-this.BOX_MARGIN,
				 border: new SUI.Border(this.BORDER_WIDTH)
				});
				cm.addClass(st);
				cm.display();

				// add the event handlers (hover and onclick)
				this._addHovers(cm);
				this._addSelectMinutes(cm, x);

				if (x == this._selDate.getMinutes() ) {
					selsecs = cm;
				}
				// move to the next cell
				l+=this.BOX_WIDTH;
			}
			// move to the next row
			t += this.BOX_HEIGHT;
		}

		return selsecs;
	},

	// draw a table of x by 8 (week no and 7 days) cells for the days of
	// the month
	_drawMonthTable: function(cont, top, left) {

	 var date = this._monthYear;
	 // get a data structure containing the data for this month
		var cal = this._getCalendar(date, this.iso);

		for (var wn in cal) {

		 var l = left;

		 // draw the week number
		 var dv = new SUI.TextBox({
			 parent: cont,
			 text: wn,
			 top: top,
			 left: l + this.BOX_MARGIN,
			 width: this.BOX_WIDTH - this.BOX_MARGIN,
			 height: this.BOX_HEIGHT,
			 border: new SUI.Border(this.BORDER_WIDTH),
			 padding: new SUI.Padding(this.BOX_MARGIN, 0)
		 });
			dv.addClass("sui-cal-weekno");
			dv.display();

			// move to the next column
			l += this.BOX_WIDTH;

			for (var i=0; i<cal[wn].length; i++) {

			 // get the day we're drawing
			 var d = cal[wn][i];

			 // determine the CSS style, does it belong to the month?
			 if (d.getMonth() == date.getMonth()) {
					var st = "sui-cal-day";
				} else {
					var st = "sui-cal-otherday";
				}
			 // is it a day of the week or weekend ?
			 if (d.getDay() == 0 || d.getDay() == 6) {
					st += " sui-cal-weekend";
				}
			 // is it the selected day ?
			 if (d.getDate() == this._selDate.getDate() &&
					d.getMonth() == this._selDate.getMonth() &&
					d.getFullYear() == this._selDate.getFullYear()) {
					st += " sui-cal-selected";
				}

			 dv = new SUI.TextBox({
				 parent: cont,
				 text: d.getDate(),
				 top: top + this.BOX_MARGIN,
				 left: l + this.BOX_MARGIN,
				 width: this.BOX_WIDTH - this.BOX_MARGIN,
				 height: this.BOX_HEIGHT - this.BOX_MARGIN,
				 border: new SUI.Border(this.BORDER_WIDTH)
			 });
				dv.addClass(st);
				dv.display();

				// add the event handlers (hover and onclick)
				this._addHovers(dv);
				this._addSelectDate(dv, d);

				// move to the next column
				l += this.BOX_WIDTH;
			}
			// move to the next row
			top += this.BOX_HEIGHT;
		}

	},

	// Return a an object with week rows (each member name is a week no) in
	// which each row has 7 elements, each representing a weekday. The whole
	// array is representing a month. To render a calendar you'll just need
	// to loop through this array.
	_getCalendar: function(d, iso) {

		var m = d.getMonth();
		var y = d.getFullYear();

		// get the first day (ISO: Monday, American: Sunday) of the first week
		// of the year (start week numbering). ISO: the week with the fourth
		// of January, American the week with the first of January
		var x = this.iso ? 4 : 1;
		var w1 = new Date(y, 0, x);
		for (; w1.getDay() != this.iso ? 1 : 0; x--) {
			w1 = new Date(y, 0, x);
		}

		// get the first day (ISO: Monday, American: Sunday) of the first week
		// of current month
		x = 2;
		do {
		 x--;
		 var fd = new Date(y, m, x);
		} while (fd.getDay() != this.iso ? 1 : 0);

		// get the week number of the first week of the month
		var wn = Math.round((fd.getTime() - w1.getTime()) / 604800000) + 1;

		var cal = {};
		do {
		 // set the week array (wn is the week no) ...
			cal[wn] = [];
			// ... fill it with the save Date()'s of the week
			for (var i=0; i<7; i++) {
			 // store 'first day' ...
				cal[wn].push(fd);
				// ... and move to the next day
				x++;
				fd = new Date(y, m, x);
			}
			wn ++;
			// as long as we're in the current month
		} while (fd.getMonth() == m);

		return cal;
	},

	// Set the date scrolling actions: next/prev month, prev/next year and
	// current date. All actions set the _mohthYear value and display the
	// calendar based on that value. The current date selection also selects
	// the current date.
	_initCalendarActions: function() {

		var that = this;

		this._actionList = new SUI.ActionList([{
				actionId: "cal.prevm",
				icon: SUI.resource.calPrev,
				title: SUI.i18n.prevMonth,
				handler: function() {
			  // display the previous month
					that._monthYear = new Date(that._monthYear.getFullYear(),
						that._monthYear.getMonth()-1, 1);
					that._drawCalendar();
				}
			},{
				actionId: "cal.nextm",
				icon: SUI.resource.calNext,
				title: SUI.i18n.nextMonth,
				handler: function() {
			  // display the next month
					that._monthYear = new Date(that._monthYear.getFullYear(),
						that._monthYear.getMonth()+1, 1);
					that._drawCalendar();
				}
			},{
				actionId: "cal.prevy",
				icon: SUI.resource.calPrev,
				title: SUI.i18n.prevYear,
				handler: function() {
					// display the previous year
					that._monthYear = new Date(that._monthYear.getFullYear()-1,
						that._monthYear.getMonth(), 1);
					that._drawCalendar();
				}
			},{
				actionId: "cal.nexty",
				icon: SUI.resource.calNext,
				title: SUI.i18n.nextYear,
				handler: function() {
					// display the next year
					that._monthYear = new Date(that._monthYear.getFullYear()+1,
						that._monthYear.getMonth(), 1);
					that._drawCalendar();
				}
			},{
				actionId: "cal.today",
				icon: SUI.resource.calToday,
				title: SUI.i18n.goToday,
				handler: function() {
					// display and select the current date
					that._monthYear = that._selDate = new Date();
					that._drawCalendar();
				}
			}
		]);

	},

	// get the input from the user on exact minutes entry
	_inputMinutes: function(value, selsecs) {
	 // if a minutes cell was selected, remove the CSS class
		if (selsecs) {
			selsecs.removeClass("sui-cal-selected");
		}
		// try to get a valid value from user input ...
		var m = parseInt(value, 10);
		if (isNaN(m)) {
			m = 0;
		}
		m = m < 0 ? 0 : m > 59 ? 59 : m;
		// ... and use that to set the selected minutes
		this._selDate.setMinutes(m);
	},

	// set the dialog's date selection and redraw the calendar
	_selectDate: function(v) {
		this._selDate.setFullYear(v.getFullYear(), v.getMonth(), v.getDate());
		this._monthYear = this._selDate;
		this._drawCalendar();
	},

	// set the dialog's hour selection and redraw the calendar
	_selectHour: function(val) {
	 this._selDate.setHours(val);
	 this._drawCalendar();
	},

	// set the dialog's minutes selection and redraw the calendar
	_selectMinutes: function(val) {
	 this._selDate.setMinutes(val);
	 this._drawCalendar();
	},

	// determine the initial dialog size
	_setDialogSize: function() {

	 var w = 0;
		var h = 0;

		// if there's only a date box ...
		if (this._dateBox) {
		 // ... add the margins to get to dialog width an height
			w = this._dateBox.width() + 2 * this.DATE_MARGIN;
			h = this.TOP_MARGIN + this._dateBox.height() + this.DATE_MARGIN;
		}

		// if there is a time box ...
	 if (this._timeBox) {

	   // ... add the margins to the height of the box ...
			var h2 = this.TOP_MARGIN + this._timeBox.height()
			 + this.TIME_BOTTOM_MARGIN;
			// ... and use that if it is larger (isn't it always?)
			if (h2 > h) {
			 h = h2;
			}

			// if there is width set by the date box already ...
			if (w) {
			 // ... add date box like margins to the time box left to
				// get the dialog width ...
				w = this._timeBox.left() + this._timeBox.width()
				 + this.DATE_MARGIN + this.BUTTON_EXTRA_SIDE_MARGIN;
			} else {
			 // ... else add margins to the time box
			 w = this._timeBox.width() + 2 * this.TIME_SIDE_MARGIN;
			}
	 }

	 // set the dialogs client size
	 this.setClientWidth(w);
		this.setClientHeight(h);
	}

});