<?xml version="1.0" encoding="UTF-8" ?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at
  
      http://www.apache.org/licenses/LICENSE-2.0
    	  
  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.
  
-->
<library>

	<class name="lzMonthView" extends="view" width="${ parent.width }" height="${ parent.height }">
		
		<!--
			Name of the trackgroup
		 -->
		<attribute name="monthViewTrackGroup" value="monthViewTrackGroup" type="string" />
		
		<!-- 
			Current Dragging object
		 -->
		<attribute name="currentDragEvent" value="null" />
		
		<!-- 
			Current dayDate that receives the track scroll over
		 -->
		<attribute name="currentOverTrackView" value="null" />
			
		<view datapath="getAppointmentsByWeekCalendarResponse/return" 
				width="${ parent.width }" height="${ Math.round( parent.height/6 ) }" >
		
			<!-- The months -->
	
			<!-- The days -->
			<view name="days" datapath="days" width="${ Math.round( parent.width/7 ) }" clip="true"
						height="${ parent.height }" bgcolor="0xDDDDDD" >
			
				<attribute name="dayDate" value="null" />
				
				<handler name="oninit">
					lz.Track.register(this, parent.parent.monthViewTrackGroup);
				</handler>
				
				<handler name="onmousetrackover">
			        this._content.setAttribute('bgcolor', 0xFF3300);
			        parent.parent.currentOverTrackView = this;
			    </handler>
			
			    <handler name="onmousetrackout">
			        this._content.setAttribute('bgcolor', 0xFFFFFF);
			        parent.parent.currentOverTrackView = null;
			    </handler>
			    
			    <handler name="onmousetrackup">
			        this._content.setAttribute('bgcolor', 0xFFFFFF);
			    </handler>
				
				<handler name="ondata" args="d">
					if(d is lz.DataNodeMixin){
						var lzDataPointer = new lz.datapointer();
						lzDataPointer.setPointer(d);
						var xmlDate = lzDataPointer.xpathQuery('tDate/text()');
						var splitDate = xmlDate.split("-");
						this.dayDate = new Date(splitDate[0], Number(splitDate[1])-1, splitDate[2]);
						this.renderView();
					}
				</handler>
				
				<method name="renderView">
					var tDay = this.dayDate.getDate();
					var tMonth = this.dayDate.getMonth();
					if (parent.parent.parent.isCurrentMonth(tMonth)) {
						this._content._title.setAttribute("fgcolor",0x000000);
						if (tDay == 1) {
							tDay = tDay + "." + canvas.monthnames[this.dayDate.getMonth()];
						}
					} else {
						this._content._title.setAttribute("fgcolor",0xBBBBBB);
					}
					this._content._title.setAttribute("text",tDay);
				</method>
				
				<view name="_content" width="${ parent.width -1 }" bgcolor="0xFFFFFF"
								height="${ parent.height -1 }" clickable="true" showhandcursor="false">
					
					<handler name="onclick">
						parent.parent.parent.parent.onNewEventDate.sendEvent(parent.dayDate);
					</handler>
					
					<handler name="onmouseover">
						this.setAttribute("bgcolor",canvas.getThemeColor('secondBorderColor'));
					</handler>
					
					<handler name="onmouseout">
						this.setAttribute("bgcolor",0xFFFFFF);
					</handler>
							
					<text name="_title">
						<handler name="onmouseover">
							this.setAttribute("fontstyle","bold");
						</handler>
						<handler name="onmouseout">
							this.setAttribute("fontstyle","plain");
						</handler>
						<handler name="onclick">
							parent.parent.parent.parent.parent.onSelectDate.sendEvent(parent.parent.dayDate);
						</handler>
					</text>
				
					<view width="${ parent.width }" y="18">
						<view datapath="appointments" bgcolor="0xA59CFC" width="${ parent.width }">
						
							<attribute name="rememberX" value="-1" />
							<attribute name="rememberY" value="-1" />
							<attribute name="mouseUpDetect" value="false" type="boolean"/>
							<attribute name="startedToDrag" value="false" type="boolean"/>
							<handler name="onmousedown">
								this.mouseUpDetect = false;
								this.startedToDrag = false;
								this.rememberX = this.getMouse("x");
								this.rememberY = this.getMouse("y");
								lz.Timer.addTimer( new LzDelegate( this, "checkIfDragging" ), 250 );
							</handler>
							<handler name="onmouseup" >
								<![CDATA[
									if (this.rememberX == this.getMouse("x")
											&& this.rememberY == this.getMouse("y")) {
										this.mouseUpDetect = true;
										var appointmentId = this.datapath.xpathQuery('appointmentId/text()');
										if ($debug) Debug.write("click ",appointmentId);
										classroot.parent.selectCalendarEvent(this);
									}
								]]>
							</handler>
							
							<method name="closeDragItem">
								var appointmentId = -1;
								lz.Track.deactivate(classroot.monthViewTrackGroup);
								
								if (classroot.currentOverTrackView == null 
													|| classroot.currentOverTrackView == parent.parent.parent) {
									if ($debug) Debug.write("Move to same Date or outside calendar");
									this.setAttribute("visibility","visible");	
								} else {
									appointmentId = Number(this.datapath.xpathQuery('appointmentId/text()'));
									if ($debug) Debug.write("Move to new Date appointmentId ",appointmentId);
								}
								
								classroot.currentDragEvent = null;
								return appointmentId;
							</method>
							
							<method name="checkIfDragging" args="tRef">
								<![CDATA[
									if (this.mouseUpDetect) {
										return;
									}
									if (this.rememberX == this.getMouse("x")
												&& this.rememberY == this.getMouse("y")) {
										lz.Timer.addTimer( new LzDelegate( this, "checkIfDragging" ), 250 );			
									} else {
										this.startedToDrag = true;
										var startx = canvas.getMouse("x")-(this.width/2);
										var starty = canvas.getMouse("y")-(this.height/2);
										classroot.currentDragEvent = new lz.dragEvent(canvas,{
													x:startx,
													startx:startx,
													y:starty,
													starty:starty,
													bgcolor:this.bgcolor,
													height:18,
													width:this.width,
													eventRef:this,
													timeText:this._time.text,
													titleText:this._title.text,
													calendarViewRef:classroot,
													fixToPositionInCalendar:false,
													isMonthMove:true										
												});
												
										lz.Track.activate(classroot.monthViewTrackGroup);
										this.setAttribute("visibility","hidden");	
									}
								]]>
							</method>
							
							<text name="_time" datapath="start" >
								<handler name="ondata" args="d">
									this.setAttribute("text",parseTimeStringFromXmlString(d.childNodes[0].data));
								</handler>
							</text>
							<text name="_title" x="36" datapath="title" text="$path{ 'text()' }" clip="true"
											width="${ parent.width-36 }" height="${ parent.height }"/>
							
						</view>
						<simplelayout axis="y" spacing="1" />
 					</view>
 					
				</view>
			
			</view>
			
		<simplelayout axis="x" spacing="0" />
		</view>
		
		<simplelayout axis="y" spacing="0" />
	
	</class>
	
</library>
	