Added ability to insert appliances into cabinet fronts
Added ability to insert appliances into cabinet fronts

--- /dev/null
+++ b/source/img/so/INCABMICRO.svg
@@ -1,1 +1,104 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
 
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="343pt"
+   height="340pt"
+   id="svg4413"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="MICRO.svg">
+  <defs
+     id="defs4415" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.6000001"
+     inkscape:cx="135.77887"
+     inkscape:cy="216.04111"
+     inkscape:document-units="pt"
+     inkscape:current-layer="layer1"
+     id="namedview4417"
+     showgrid="false"
+     inkscape:window-width="1600"
+     inkscape:window-height="881"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata4419">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2.30999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="M 61.85655,74.816408 388.71369,50.691889 368.44936,279.53301 87.180941,384.2498 z"
+       id="path4513"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2.30999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="M 83.447761,93.19049 340.98047,68.035297 331.83444,288.36314 104.33064,372.89485 z"
+       id="path4537"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2.30999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="M 81.542471,91.795924 102.53093,371.44148 99.335821,368.71304 78.346261,89.620224 z"
+       id="path4543"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2.30999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="M 78.658401,89.760108 333.3202,67.456172 340.81052,67.925571 82.918851,91.134512 z"
+       id="path5057"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2.30999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 346.50886,67.351618 35.4609,-4.981044 -1.45201,19.393956 -35.20527,6.047985 z"
+       id="path3016"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2.30999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 124.37499,342.50001 c 0,0 -16.25,-228.75 -13.125,-228.125 3.125,0.625 215.62499,-28.124995 215.62499,-28.124995 l -10,192.499995 z"
+       id="path3018"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="csccc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2.30999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 339.06248,284.68751 c 0.3125,-6.875 0.625,-3.30832 0.9375,-19.0625 l 25.9375,-6.5625 -1.5625,15.9375 z"
+       id="path3020"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:2.30999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 345.436,94.155701 c 2.20971,0.441942 34.91339,-6.629125 34.91339,-6.629125 l -7.07106,87.062514 -31.59883,4.6404 z"
+       id="path3024"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+  </g>
+</svg>
+

--- a/source/lib/scripts/CabinetEditor/CabinetEditor.js
+++ b/source/lib/scripts/CabinetEditor/CabinetEditor.js
@@ -12,6 +12,7 @@
 

 		'CabinetEditor/Schematic/Schematic',

 		'CabinetEditor/Schematic/SchematicObject',

+		'CabinetEditor/Schematic/Attachments/CabinetAttachment',

 		'CabinetEditor/Schematic/Other/Wall',

 

 		'CabinetEditor/Tools/Item/EditCabinetTool',

@@ -22,7 +23,8 @@
 

 		'Geometry/Point2D',

 

-		'Util/UI'

+		'Util/UI',

+		'Util/Class'

 

 	],

 	function(

@@ -32,6 +34,7 @@
 

 		Schematic,

 		SchematicObject,

+		CabinetAttachment,

 		Wall,

 

 		EditCabinetTool,

@@ -42,7 +45,8 @@
 

 		Point,

 		

-		UI

+		UI,

+		Class

 

 	){

 

@@ -273,23 +277,23 @@
 		// Setup events for Front View Canvas

 		this.fv_canvas.onmousedown = function(t){

 			return function(e){

-				t.active_tool.mouse_down_fv(e);

+				t.active_tool.mouseDownFrontView(e);

 			};

 		}(this);

 		this.fv_canvas.onmousemove = function(t){

 			return function(e){

-				t.active_tool.mouse_move_fv(e);

+				t.active_tool.mouseMoveFrontView(e);

 			};

 		}(this);

 		// Setup events for Detail View Canvas

 		this.dv_canvas.onmousedown = function(t){

 			return function(e){

-				t.active_tool.mouse_down_dv(e);

+				t.active_tool.mouseDownDetailView(e);

 			};

 		}(this);

 		this.dv_canvas.onmousemove = function(t){

 			return function(e){

-				t.active_tool.mouse_move_dv(e);

+				t.active_tool.mouseMoveDetailView(e);

 			};

 		}(this);

 

@@ -594,7 +598,6 @@
 

 		this.fv_buffer_ctx.scale(this.scale_fv, this.scale_fv);

 		this.fv_buffer_ctx.translate(this.schematic.offset_x_fv, (this.schematic.ceiling_height+10.0));

-

 		it = this.schematic.objectIterator();

 		while(it.hasNext()){

 

@@ -626,6 +629,9 @@
 		}

 

 		if(this.active_pick != null) this.active_pick.renderFrontView(this.fv_buffer_ctx, this);

+

+		// Tool Hud

+		this.active_tool.renderFrontView(this.fv_buffer_ctx);

 

 		// Clear screen

 		this.fv_ctx.clearRect(0, 0, this.fv_canvas.width, this.fv_canvas.height);

@@ -913,14 +919,16 @@
 		this.object_groups.length = 0;

 

 		for(i = 0; i < this.schematic.objects.length; i++){

-

-			// ignore objects without front views

-			if(!this.schematic.objects[i].hasFrontView()){}

-			

+			// ignore objects without front views and cabient attachments

+			if(!this.schematic.objects[i].hasFrontView() || Class.isChild(CabinetAttachment, this.schematic.objects[i])){}

+

 			// TODO: corner objects can not be base groups

 			else if(this.object_groups.length == 0){

+

 				this.object_groups.push([this.schematic.objects[i]]);

+

 			} else {

+

 				grouped = false;

 				for(j = 0; j < this.object_groups.length; j++){

 					for(k = 0; k < this.object_groups[j].length; k++){

@@ -968,8 +976,10 @@
 			group_width = group_max-group_min;

 

 			for(j = 0; j < this.object_groups[i].length; j++){

+

 				obj = this.object_groups[i][j];

 				obj.fv_x = left_distance + group_offsets[j];

+

 			}

 

 			left_distance += group_width+10;				// TODO: 10 = break_length


--- a/source/lib/scripts/CabinetEditor/Schematic/Cabinet/Cabinet.js
+++ b/source/lib/scripts/CabinetEditor/Schematic/Cabinet/Cabinet.js
@@ -325,6 +325,31 @@
 	Cabinet.prototype.add_faces = function(ptl, ptr, face_angle, vertices, normals, indices, texcoords){
 
 		this.faces.front_face.add_3D(ptl, ptr, face_angle, vertices, normals, indices, texcoords, this);
+
+	};
+
+	Cabinet.prototype.faceAtFrontView = function(y){
+
+		var topY = this.z + this.d,
+		    face = this.faces.front_face,
+		    i,
+		    currentFront;
+
+		if(face != null){
+			for(i = 0; i < face.fronts.length; i++){
+
+				currentFront = face.fronts[i];
+
+				if(topY > y && topY - currentFront.height < y){
+					return {index: i, front: currentFront, height: topY};
+				}
+
+				topY -= currentFront.height;
+
+			}
+		}
+
+		return null;
 
 	};
 

--- a/source/lib/scripts/CabinetEditor/Schematic/Other/Measurement.js
+++ b/source/lib/scripts/CabinetEditor/Schematic/Other/Measurement.js
@@ -76,6 +76,10 @@
 		};
 
 		Measurement.prototype.has3D = function(){
+			return false;
+		};
+
+		Measurement.prototype.hasFrontView = function(){
 			return false;
 		};
 

--- a/source/lib/scripts/CabinetEditor/Schematic/Other/P2PMeasurement.js
+++ b/source/lib/scripts/CabinetEditor/Schematic/Other/P2PMeasurement.js
@@ -60,6 +60,10 @@
 		};
 
 		P2PMeasurement.prototype.has3D = function(){
+			return false;
+		};
+
+		P2PMeasurement.prototype.hasFrontView = function(){
 			return false;
 		};
 

--- a/source/lib/scripts/CabinetEditor/Schematic/SchematicObject.js
+++ b/source/lib/scripts/CabinetEditor/Schematic/SchematicObject.js
@@ -325,6 +325,18 @@
 		return null;
 	};
 
+	SchematicObject.prototype.isMouseOverFrontView = function(x, y){
+
+		if(	   x >= this.fv_x
+			&& x <= this.fv_x+this.getFrameWidth()
+			&& y >= this.z
+			&& y <= this.z+this.d)
+				return true;
+
+		return false;
+
+	};
+
 	/**
 	 * Returns the pick the mouse is over for this object
 	 * @function

--- /dev/null
+++ b/source/lib/scripts/CabinetEditor/Tools/Item/AddCabinetApplianceTool.js
@@ -1,1 +1,238 @@
-
+/**
+ * @file Tool for adding Cabinets, Appliances, etc. to the Schematic
+ * @author Michael Marques <dryerzinia@gmail.com>
+ * @module Tool/AddCabinetTool
+ */
+
+define(
+	[
+
+	 	'CabinetEditor/Schematic/SchematicObject',
+	 	'CabinetEditor/Schematic/Cabinet/Cabinet',
+	 	'CabinetEditor/Schematic/Cabinet/Face/Kick',
+	 	'CabinetEditor/Schematic/Cabinet/Face/Rail',
+	 	'CabinetEditor/Schematic/Cabinet/Face/ApplianceFront',
+	 	'CabinetEditor/Tools/Tool',
+
+	 	'CabinetEditor/Config',
+	 	'CabinetEditor/Helper',
+
+	 	'Geometry/Point2D',
+
+	 	'Util/UI',
+	 	'Util/Class'
+
+	 ],
+	 function(
+
+		SchematicObject,
+		Cabinet,
+		Kick,
+		Rail,
+		ApplianceFront,
+		Tool,
+
+		Config,
+		Helper,
+
+		Point,
+
+		UI,
+		Class
+
+	 ){
+
+	/**
+	 * Tool for Adding Cabinets to the schematic
+	 * @constructor
+	 * @augments Tool
+	 * @property {SchematicObject} cabinet SchematicObject to add to the schematic
+	 * @property {Point} downPoint Schematic Coordinates where mouse went down
+	 * @property {Point} realDownPoint Document Coordinates where mouse went down
+	 *  (for dragging)
+	 */
+	function AddCabinetApplianceTool(editor, lastTool, applianceType, defaultHeight, defaultWidth){
+
+		Tool.call(this, editor);
+
+		this.lastTool = lastTool;
+
+		this.applianceType = applianceType;
+		this.defaultHeight = defaultHeight;
+		this.defaultWidth = defaultWidth;
+
+		this.mouseFrontViewPt = new Point(0, 0);
+		this.downPt = null;
+		this.clicking_fv = false;
+
+		this.currentFront = null;
+		this.currentFrontIndex = -1;
+		this.currentFrontHeight = 0;
+		this.currentCabinet = null;
+
+	};
+
+	Class.extend(Tool, AddCabinetApplianceTool);
+
+
+	AddCabinetApplianceTool.prototype.mouseUp = function(e){
+
+		// If we are over a face and the mouse hasn't moved too far from the down position
+		// then replace that face in the cabinet with the applianceFront object
+		// And change back to last tool
+		var pt = UI.correctOffset(this.editor.fv_canvas, UI.eventPoint(e));
+
+		this.clicking_fv = false;
+
+		this.fv_is_dragging = false;
+		
+		// Not dragging
+		if(pt.distanceToPoint(this.downPt) < 3){
+
+			if(this.currentCabinet !== null){
+
+				this.currentCabinet.faces.front_face.fronts[this.currentFrontIndex] = new ApplianceFront(this.currentFront.height, this.applianceType);
+
+				this.editor.setTool(this.lastTool);
+				// TODO autosave
+				this.editor.animate();
+
+			}
+
+		}
+
+	};
+
+	AddCabinetApplianceTool.prototype.mouseDownFrontView = function(e){
+
+		// Mark down position
+		this.downPt = UI.correctOffset(this.editor.fv_canvas, UI.eventPoint(e));
+
+		if(e.which == 1){
+			this.clicking_fv = true;
+		}
+		
+	};
+
+	AddCabinetApplianceTool.prototype.mouseMoveFrontView = function(e){
+
+		var pt = UI.correctOffset(this.editor.fv_canvas, UI.eventPoint(e)),
+
+			correct_x = pt.x/this.editor.scale_fv-this.editor.schematic.offset_x_fv,
+			correct_y = pt.y/-this.editor.scale_fv+(this.editor.schematic.ceiling_height+10.0),	// TODO: +10 shift global variable
+
+			front, found;
+
+		this.mouseFrontViewPt.setXY(correct_x, correct_y);
+
+		// Handle dragging
+
+		// Find face under cursor
+		it = editor.schematic.objectIterator();
+		found = false;
+		while(it.hasNext()){
+			obj = it.next();
+
+			// We are only looking at cabinet objects
+			if(Class.isChild(Cabinet, obj)){
+
+				// If mouse is over them figure out if we are over
+				// a none kick/rail face and return the face, its index
+				// and save the cabinet reference and face index
+				// as currently moused over for when we click
+				if(obj.isMouseOverFrontView(correct_x, correct_y)){
+
+					front = obj.faceAtFrontView(correct_y);
+
+					if(front !== null && !(front.front instanceof Kick) && !(front.front instanceof Rail)){
+
+						this.currentFront = front.front;
+						this.currentFrontIndex = front.index;
+						this.currentFrontHeight = front.height;
+						this.currentCabinet = obj;
+
+						found = true;
+
+						break;
+					}
+
+				}
+
+			}
+
+		}
+
+		if(!found){
+
+			this.currentFront = null;
+			this.currentFrontHeight = 0;
+			this.currentFrontIndex = -1;
+			this.currentCabinet = null;
+
+		}
+
+		this.handleFrontViewDrag(pt);
+
+		editor.last_mouse_x_fv = pt.x;
+		editor.last_mouse_y_fv = pt.y;
+
+		editor.animate();
+
+	};
+
+	AddCabinetApplianceTool.prototype.renderFrontView = function(ctx){
+
+		// If we are moused over a face
+		// Draw appliance name and box in face
+		// else just draw a box at the cursor location
+
+		var height, frameWidth, rightStyleWidth = 0, leftStyleWidth = 0, x, y;
+
+		if(this.currentFront !== null){
+
+			rightStyleWidth = this.currentCabinet.faces.front_face.right_style_width;
+			leftStyleWidth = this.currentCabinet.faces.front_face.left_style_width;
+
+			x = this.currentCabinet.fv_x + leftStyleWidth;
+			y = -this.currentFrontHeight;
+
+			frameWidth = this.currentCabinet.getFrameWidth() - leftStyleWidth - rightStyleWidth;
+			height = this.currentFront.height;
+
+		} else {
+
+			x = this.mouseFrontViewPt.x - this.defaultWidth / 2;
+			y = -this.mouseFrontViewPt.y - this.defaultHeight / 2;
+			frameWidth = this.defaultWidth;
+			height = this.defaultHeight;
+
+		}
+
+		ctx.rect(x, y, frameWidth, height);
+		ctx.stroke();
+
+		ctx.fillStyle = ctx.strokeStyle;
+		ctx.font = "4px Arial";
+		ctx.fillText(this.applianceType, x + frameWidth / 2 - ctx.measureText(this.applianceType).width / 2, y + height / 2 + 2);
+
+	};
+
+	AddCabinetApplianceTool.prototype.mouseDownDetailView = function(e){
+	};
+	AddCabinetApplianceTool.prototype.mouseMoveDetailView = function(e){
+	};
+	AddCabinetApplianceTool.prototype.renderDetailView = function(ctx){
+	};
+
+	AddCabinetApplianceTool.prototype.keyDown = function(e){
+
+		if(e.keyCode == 27){	// Escape
+			this.editor.setTool(this.lastTool);
+		}
+
+	};
+
+	return AddCabinetApplianceTool;
+
+});
+

--- a/source/lib/scripts/CabinetEditor/Tools/Item/EditCabinetTool.js
+++ b/source/lib/scripts/CabinetEditor/Tools/Item/EditCabinetTool.js
@@ -147,7 +147,7 @@
 
 	};
 
-	EditCabinetTool.prototype.mouse_down_fv = function(e){
+	EditCabinetTool.prototype.mouseDownFrontView = function(e){
 
 		if(e.which == 1){
 
@@ -168,7 +168,7 @@
 		}
 	};
 
-	EditCabinetTool.prototype.mouse_move_fv = function(e){
+	EditCabinetTool.prototype.mouseMoveFrontView = function(e){
 
 		var pt = UI.correctOffset(this.editor.fv_canvas, new Point(e.pageX, e.pageY)),
 		correct_x = pt.x/this.editor.scale_fv-this.editor.schematic.offset_x_fv,
@@ -191,12 +191,7 @@
 			pick = obj.getPickFrontView(correct_x, correct_y);
 			if(pick != null) picks.push(pick);
 
-			// Check for moused over
-			fw = obj.getFrameWidth();
-			if(correct_x >= obj.fv_x
-					&& correct_x <= obj.fv_x+fw
-					&& correct_y >= obj.z
-					&& correct_y <= obj.z+obj.d){
+			if(!this.fv_is_dragging && obj.isMouseOverFrontView(correct_x, correct_y)){
 				found = true;
 				this.editor.mousedover_cabinet = obj;
 				this.editor.animate();
@@ -215,38 +210,7 @@
 			}
 		} else {
 
-			this.editor.fv_canvas.style.cursor = 'auto';
-
-			// Check for dragging of front view
-			if(this.clicking_fv){
-
-				this.fv_is_dragging = true;
-
-				var fv_window_width = this.editor.fv_canvas.width/this.editor.scale_fv;
-
-				this.editor.schematic.offset_x_fv -= (this.editor.last_mouse_x_fv-pt.x)/this.editor.scale_fv;
-
-				if(fv_window_width > this.editor.front_view_width){
-
-					if(10 > this.editor.schematic.offset_x_fv)
-						this.editor.schematic.offset_x_fv = 10;
-
-					if(this.editor.schematic.offset_x_fv > fv_window_width-this.editor.front_view_width)
-						this.editor.schematic.offset_x_fv = fv_window_width-this.editor.front_view_width;
-
-				} else {
-
-					if(10 < this.editor.schematic.offset_x_fv)
-						this.editor.schematic.offset_x_fv = 10;
-
-					if(this.editor.schematic.offset_x_fv < -this.editor.front_view_width+fv_window_width)
-						this.editor.schematic.offset_x_fv = -this.editor.front_view_width+fv_window_width;
-
-				}
-
-				this.editor.animate();
-
-			}
+			this.handleFrontViewDrag(pt);
 
 		}
 
@@ -255,13 +219,13 @@
 
 	};
 
-	EditCabinetTool.prototype.mouse_down_dv = function(e){
+	EditCabinetTool.prototype.mouseDownDetailView = function(e){
 
 		if(e.which == 1) this.clicking_dv = true;
 
 	};
 
-	EditCabinetTool.prototype.mouse_move_dv = function(e){
+	EditCabinetTool.prototype.mouseMoveDetailView = function(e){
 
 		var cvs, pt, frame_width, s, correct_x, correct_y, cab, pick;
 
@@ -444,7 +408,7 @@
 				pt_dist = 100;
 			} else if(picks[i].pt != undefined){
 				distance = new Point(x, y).distanceToPoint(picks[i].pt);
-				// TODO: Fix this it doesnt work need to detect which object cursore is next to better
+				// TODO: Fix this it doesn't work need to detect which object cursor is next to better
 				pt_dist = new Point(x, y).distanceToPoint(new Point(picks[i].object.x, picks[i].object.y)) - picks[i].pt.distanceToPoint(new Point(picks[i].object.x, picks[i].object.y));
 			}
 

--- a/source/lib/scripts/CabinetEditor/Tools/Tool.js
+++ b/source/lib/scripts/CabinetEditor/Tools/Tool.js
@@ -59,14 +59,14 @@
 	 * @function
 	 * @param {mouse_event} e Contains the location of the mouse
 	 */
-	Tool.prototype.mouse_down_fv = function(e){
+	Tool.prototype.mouseDownFrontView = function(e){
 	};
 	/**
 	 * Mouse move event on Front View Canvas
 	 * @function
 	 * @param {mouse_event} e Contains the location of the mouse
 	 */
-	Tool.prototype.mouse_move_fv = function(e){
+	Tool.prototype.mouseMoveFrontView = function(e){
 	};
 	/**
 	 * Render tool info on Front View
@@ -81,14 +81,14 @@
 	 * @function
 	 * @param {mouse_event} e Contains the location of the mouse
 	 */
-	Tool.prototype.mouse_down_dv = function(e){
+	Tool.prototype.mouseDownDetailView = function(e){
 	};
 	/**
 	 * Mouse move event on Detail View Canvas
 	 * @function
 	 * @param {mouse_event} e Contains the location of the mouse
 	 */
-	Tool.prototype.mouse_move_dv = function(e){
+	Tool.prototype.mouseMoveDetailView = function(e){
 	};
 	/**
 	 * Render tool on the Detail View Canvas
@@ -97,6 +97,43 @@
 	 */
 	Tool.prototype.renderDetailView = function(ctx){
 	};
+
+	Tool.prototype.handleFrontViewDrag = function(pt){
+
+		this.editor.fv_canvas.style.cursor = 'auto';
+
+		// Check for dragging of front view
+		if(this.clicking_fv){
+
+			this.fv_is_dragging = true;
+
+			var fv_window_width = this.editor.fv_canvas.width/this.editor.scale_fv;
+
+			this.editor.schematic.offset_x_fv -= (this.editor.last_mouse_x_fv-pt.x)/this.editor.scale_fv;
+
+			if(fv_window_width > this.editor.front_view_width){
+
+				if(10 > this.editor.schematic.offset_x_fv)
+					this.editor.schematic.offset_x_fv = 10;
+
+				if(this.editor.schematic.offset_x_fv > fv_window_width-this.editor.front_view_width)
+					this.editor.schematic.offset_x_fv = fv_window_width-this.editor.front_view_width;
+
+			} else {
+
+				if(10 < this.editor.schematic.offset_x_fv)
+					this.editor.schematic.offset_x_fv = 10;
+
+				if(this.editor.schematic.offset_x_fv < -this.editor.front_view_width+fv_window_width)
+					this.editor.schematic.offset_x_fv = -this.editor.front_view_width+fv_window_width;
+
+			}
+
+			this.editor.animate();
+
+		}
+
+	}
 
 	Tool.wasDragging = function(downPoint, realDownPoint, cursorPoint, tolerance){
 

--- a/source/lib/scripts/DefaultCabinets.js
+++ b/source/lib/scripts/DefaultCabinets.js
@@ -662,6 +662,8 @@
 	DefaultCabinets.appliance.OVEN  = new Appliance(-1,Layer.LOWER,0,0,24,24,0,30,0,'oven');
 	DefaultCabinets.appliance.MICRO = new Appliance(-1,Layer.COUNTER_TOP,0,0,24,20,34.5,14,0,'microwave');
 
+	DefaultCabinets.appliance.INCABMICRO = "Microwave";
+
 	DefaultCabinets.appliance.Cooktop = new Cooktop(-1, -1, 'center', 0, 0, 36, 24, 0, 0, 0);
 
 	DefaultCabinets.appliance.UndermountSingle = new Sink(-1, -1, 'center', 'single', 'round', 0, 0, 24, 24, 0, 0, 0);

--- a/source/lib/scripts/GUI/ItemSelector.js
+++ b/source/lib/scripts/GUI/ItemSelector.js
@@ -6,6 +6,7 @@
 	 	'CabinetEditor/Schematic/Other/WallInserts/WallInsert',
 	 	'CabinetEditor/Schematic/Attachments/CabinetAttachment',
 	 	'CabinetEditor/Tools/Item/AddCabinetTool',
+	 	'CabinetEditor/Tools/Item/AddCabinetApplianceTool',
 	 	'CabinetEditor/Tools/Wall/AddWallInsertTool',
 	 	'CabinetEditor/Tools/Item/AddAttachmentTool'
 	],
@@ -16,6 +17,7 @@
 		WallInsert,
 		CabinetAttachment,
 		AddCabinetTool,
+		AddCabinetApplianceTool,
 		AddWallInsertTool,
 		AddAttachmentTool
 	){
@@ -110,6 +112,18 @@
 									)
 								);
 
+							} else if(typeof(cab) === 'string' || cab instanceof String){
+
+								editor.setTool(
+									new AddCabinetApplianceTool(
+										editor,
+										editor.active_tool,
+										cab,
+										20,
+										30
+									)
+								);
+
 							} else {
 
 								editor.setTool(

--- a/source/lib/scripts/Geometry/Point2D.js
+++ b/source/lib/scripts/Geometry/Point2D.js
@@ -40,6 +40,20 @@
 				return true;
 
 			return false;
+
+		};
+
+		Point2D.prototype.set = function(p){
+
+			this.x = p.x;
+			this.y = p.y;
+
+		};
+
+		Point2D.prototype.setXY = function(x, y){
+
+			this.x = x;
+			this.y = y;
 
 		};