2014-01-29 19:09:30 -08:00
|
|
|
|
/*
|
2017-06-23 15:13:39 -07:00
|
|
|
|
Copyright (c) 2017, Lars Brubaker, John Lewin
|
2014-01-29 19:09:30 -08:00
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
2015-04-08 15:20:10 -07:00
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
2014-01-29 19:09:30 -08:00
|
|
|
|
|
|
|
|
|
|
1. Redistributions of source code must retain the above copyright notice, this
|
2015-04-08 15:20:10 -07:00
|
|
|
|
list of conditions and the following disclaimer.
|
2014-01-29 19:09:30 -08:00
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
|
|
this list of conditions and the following disclaimer in the documentation
|
2015-04-08 15:20:10 -07:00
|
|
|
|
and/or other materials provided with the distribution.
|
2014-01-29 19:09:30 -08:00
|
|
|
|
|
|
|
|
|
|
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 OWNER 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.
|
|
|
|
|
|
|
|
|
|
|
|
The views and conclusions contained in the software and documentation are those
|
2015-04-08 15:20:10 -07:00
|
|
|
|
of the authors and should not be interpreted as representing official policies,
|
2014-01-29 19:09:30 -08:00
|
|
|
|
either expressed or implied, of the FreeBSD Project.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2017-06-23 15:13:39 -07:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Linq;
|
2014-01-29 19:09:30 -08:00
|
|
|
|
using MatterHackers.Agg;
|
2014-06-19 15:55:20 -07:00
|
|
|
|
using MatterHackers.Agg.UI;
|
2017-06-23 15:13:39 -07:00
|
|
|
|
using MatterHackers.Localizations;
|
|
|
|
|
|
using MatterHackers.MatterControl.ConfigurationPage;
|
2014-06-19 15:55:20 -07:00
|
|
|
|
using MatterHackers.MatterControl.CustomWidgets;
|
2014-06-11 14:52:58 -07:00
|
|
|
|
using MatterHackers.MatterControl.PrinterCommunication;
|
2015-04-08 15:20:10 -07:00
|
|
|
|
using MatterHackers.MatterControl.PrinterControls;
|
2014-06-19 15:55:20 -07:00
|
|
|
|
using MatterHackers.MatterControl.SlicerConfiguration;
|
2014-01-29 19:09:30 -08:00
|
|
|
|
|
|
|
|
|
|
namespace MatterHackers.MatterControl
|
|
|
|
|
|
{
|
2017-02-23 12:43:37 -08:00
|
|
|
|
public class ManualPrinterControls : GuiWidget
|
2015-04-08 15:20:10 -07:00
|
|
|
|
{
|
2015-04-09 17:45:14 -07:00
|
|
|
|
static public RootedObjectEventHandler AddPluginControls = new RootedObjectEventHandler();
|
|
|
|
|
|
private static bool pluginsQueuedToAdd = false;
|
2015-04-08 15:20:10 -07:00
|
|
|
|
|
2017-02-23 12:43:37 -08:00
|
|
|
|
public ManualPrinterControls()
|
|
|
|
|
|
{
|
2017-05-24 14:19:02 -07:00
|
|
|
|
this.BackgroundColor = ApplicationController.Instance.Theme.TabBodyBackground;
|
2017-02-23 12:43:37 -08:00
|
|
|
|
AnchorAll();
|
2017-08-06 17:33:42 -07:00
|
|
|
|
|
|
|
|
|
|
AddChild(new ManualPrinterControlsDesktop());
|
2017-06-28 09:17:17 -07:00
|
|
|
|
}
|
2017-02-23 12:43:37 -08:00
|
|
|
|
|
2017-06-28 09:17:17 -07:00
|
|
|
|
public override void OnLoad(EventArgs args)
|
|
|
|
|
|
{
|
2017-02-23 12:43:37 -08:00
|
|
|
|
if (!pluginsQueuedToAdd && ActiveSliceSettings.Instance.GetValue("include_firmware_updater") == "Simple Arduino")
|
|
|
|
|
|
{
|
2017-06-28 09:17:17 -07:00
|
|
|
|
UiThread.RunOnIdle(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
AddPluginControls.CallEvents(this, null);
|
|
|
|
|
|
pluginsQueuedToAdd = false;
|
|
|
|
|
|
});
|
2017-02-23 12:43:37 -08:00
|
|
|
|
pluginsQueuedToAdd = true;
|
|
|
|
|
|
}
|
2017-06-28 09:17:17 -07:00
|
|
|
|
|
|
|
|
|
|
base.OnLoad(args);
|
2017-02-23 12:43:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class ManualPrinterControlsDesktop : ScrollableWidget
|
|
|
|
|
|
{
|
2015-04-08 15:20:10 -07:00
|
|
|
|
private DisableableWidget fanControlsContainer;
|
2016-01-13 14:11:47 -08:00
|
|
|
|
private DisableableWidget macroControlsContainer;
|
2016-12-08 15:39:23 -08:00
|
|
|
|
private DisableableWidget actionControlsContainer;
|
2016-01-13 16:11:13 -08:00
|
|
|
|
private DisableableWidget tuningAdjustmentControlsContainer;
|
2017-08-06 18:17:46 -07:00
|
|
|
|
private MovementControls movementControlsContainer;
|
2017-08-06 19:22:47 -07:00
|
|
|
|
private DisableableWidget calibrationControlsContainer;
|
2016-01-13 16:11:13 -08:00
|
|
|
|
|
2017-06-23 15:13:39 -07:00
|
|
|
|
private EventHandler unregisterEvents;
|
|
|
|
|
|
|
2017-02-23 12:43:37 -08:00
|
|
|
|
public ManualPrinterControlsDesktop()
|
2015-04-08 15:20:10 -07:00
|
|
|
|
{
|
2017-06-23 15:13:39 -07:00
|
|
|
|
ScrollArea.HAnchor |= HAnchor.ParentLeftRight;
|
2016-10-05 10:36:07 -07:00
|
|
|
|
AnchorAll();
|
|
|
|
|
|
AutoScroll = true;
|
|
|
|
|
|
|
2017-02-23 12:43:37 -08:00
|
|
|
|
HAnchor = HAnchor.Max_FitToChildren_ParentWidth;
|
|
|
|
|
|
VAnchor = VAnchor.ParentBottomTop;
|
2015-04-08 15:20:10 -07:00
|
|
|
|
|
2017-08-06 18:17:46 -07:00
|
|
|
|
int headingPointSize = 18;
|
|
|
|
|
|
|
2017-06-23 15:13:39 -07:00
|
|
|
|
var controlsTopToBottomLayout = new FlowLayoutWidget(FlowDirection.TopToBottom)
|
|
|
|
|
|
{
|
|
|
|
|
|
HAnchor = HAnchor.Max_FitToChildren_ParentWidth,
|
|
|
|
|
|
VAnchor = VAnchor.FitToChildren,
|
|
|
|
|
|
Name = "ManualPrinterControls.ControlsContainer",
|
|
|
|
|
|
Margin = new BorderDouble(0)
|
|
|
|
|
|
};
|
2017-08-06 17:44:57 -07:00
|
|
|
|
this.AddChild(controlsTopToBottomLayout);
|
2016-11-30 13:31:19 -08:00
|
|
|
|
|
2017-08-06 17:44:57 -07:00
|
|
|
|
actionControlsContainer = new ActionControls();
|
|
|
|
|
|
controlsTopToBottomLayout.AddChild(actionControlsContainer);
|
|
|
|
|
|
|
2017-08-06 18:17:46 -07:00
|
|
|
|
movementControlsContainer = new MovementControls(headingPointSize);
|
2017-08-06 17:44:57 -07:00
|
|
|
|
controlsTopToBottomLayout.AddChild(movementControlsContainer);
|
2015-04-23 20:19:00 -07:00
|
|
|
|
|
2017-06-23 15:13:39 -07:00
|
|
|
|
if (!ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.has_hardware_leveling))
|
|
|
|
|
|
{
|
2017-08-06 19:22:47 -07:00
|
|
|
|
calibrationControlsContainer = new CalibrationSettingsWidget(ApplicationController.Instance.Theme.ButtonFactory, headingPointSize);
|
|
|
|
|
|
controlsTopToBottomLayout.AddChild(calibrationControlsContainer);
|
2017-06-23 15:13:39 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-06 18:17:46 -07:00
|
|
|
|
macroControlsContainer = new MacroControls(headingPointSize);
|
2017-08-06 17:44:57 -07:00
|
|
|
|
controlsTopToBottomLayout.AddChild(macroControlsContainer);
|
2016-12-08 15:39:23 -08:00
|
|
|
|
|
2017-06-23 15:13:39 -07:00
|
|
|
|
var linearPanel = new FlowLayoutWidget()
|
|
|
|
|
|
{
|
|
|
|
|
|
HAnchor = HAnchor.ParentLeftRight
|
|
|
|
|
|
};
|
2015-04-23 20:19:00 -07:00
|
|
|
|
controlsTopToBottomLayout.AddChild(linearPanel);
|
|
|
|
|
|
|
2017-08-06 18:17:46 -07:00
|
|
|
|
fanControlsContainer = new FanControls(headingPointSize);
|
2016-07-12 17:46:48 -07:00
|
|
|
|
if (ActiveSliceSettings.Instance.GetValue<bool>(SettingsKey.has_fan))
|
2015-04-08 15:20:10 -07:00
|
|
|
|
{
|
|
|
|
|
|
controlsTopToBottomLayout.AddChild(fanControlsContainer);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-02-23 15:24:27 -08:00
|
|
|
|
#if !__ANDROID__
|
2017-08-06 18:17:46 -07:00
|
|
|
|
controlsTopToBottomLayout.AddChild(new PowerControls(headingPointSize));
|
2017-02-23 15:24:27 -08:00
|
|
|
|
#endif
|
2017-08-06 18:17:46 -07:00
|
|
|
|
tuningAdjustmentControlsContainer = new AdjustmentControls(headingPointSize);
|
2017-08-06 17:44:57 -07:00
|
|
|
|
controlsTopToBottomLayout.AddChild(tuningAdjustmentControlsContainer);
|
2015-04-23 20:19:00 -07:00
|
|
|
|
|
2017-08-06 17:44:57 -07:00
|
|
|
|
// HACK: this is a hack to make the layout engine fire again for this control
|
|
|
|
|
|
UiThread.RunOnIdle(() => tuningAdjustmentControlsContainer.Width = tuningAdjustmentControlsContainer.Width + 1);
|
2016-12-08 15:39:23 -08:00
|
|
|
|
|
2017-08-06 17:44:57 -07:00
|
|
|
|
PrinterConnection.Instance.CommunicationStateChanged.RegisterEvent(onPrinterStatusChanged, ref unregisterEvents);
|
|
|
|
|
|
PrinterConnection.Instance.EnableChanged.RegisterEvent(onPrinterStatusChanged, ref unregisterEvents);
|
|
|
|
|
|
|
|
|
|
|
|
SetVisibleControls();
|
2015-04-08 15:20:10 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-06 17:44:57 -07:00
|
|
|
|
public override void OnClosed(ClosedEventArgs e)
|
2015-04-08 15:20:10 -07:00
|
|
|
|
{
|
2017-08-06 17:44:57 -07:00
|
|
|
|
unregisterEvents?.Invoke(this, null);
|
|
|
|
|
|
base.OnClosed(e);
|
2015-04-08 15:20:10 -07:00
|
|
|
|
}
|
2014-01-29 19:09:30 -08:00
|
|
|
|
|
2015-04-09 17:45:14 -07:00
|
|
|
|
private void onPrinterStatusChanged(object sender, EventArgs e)
|
2015-04-08 15:20:10 -07:00
|
|
|
|
{
|
2015-04-09 17:45:14 -07:00
|
|
|
|
SetVisibleControls();
|
2017-06-23 15:13:39 -07:00
|
|
|
|
UiThread.RunOnIdle(this.Invalidate);
|
2015-04-08 15:20:10 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void SetVisibleControls()
|
|
|
|
|
|
{
|
2016-07-21 15:05:59 -07:00
|
|
|
|
if (!ActiveSliceSettings.Instance.PrinterSelected)
|
2015-04-08 15:20:10 -07:00
|
|
|
|
{
|
2017-02-23 16:30:00 -08:00
|
|
|
|
movementControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
|
|
|
|
|
fanControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
|
|
|
|
|
macroControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
|
|
|
|
|
actionControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
2017-08-06 19:22:47 -07:00
|
|
|
|
calibrationControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
2017-02-23 16:30:00 -08:00
|
|
|
|
tuningAdjustmentControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
2015-04-08 15:20:10 -07:00
|
|
|
|
}
|
|
|
|
|
|
else // we at least have a printer selected
|
|
|
|
|
|
{
|
2017-06-13 17:22:49 -07:00
|
|
|
|
switch (PrinterConnection.Instance.CommunicationState)
|
2015-04-08 15:20:10 -07:00
|
|
|
|
{
|
2017-06-13 17:32:38 -07:00
|
|
|
|
case CommunicationStates.Disconnecting:
|
|
|
|
|
|
case CommunicationStates.ConnectionLost:
|
|
|
|
|
|
case CommunicationStates.Disconnected:
|
|
|
|
|
|
case CommunicationStates.AttemptingToConnect:
|
|
|
|
|
|
case CommunicationStates.FailedToConnect:
|
2017-02-23 16:30:00 -08:00
|
|
|
|
movementControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.ConfigOnly);
|
|
|
|
|
|
fanControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
|
|
|
|
|
macroControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.ConfigOnly);
|
|
|
|
|
|
actionControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
|
|
|
|
|
tuningAdjustmentControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
2017-08-06 19:22:47 -07:00
|
|
|
|
calibrationControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
2016-01-13 07:39:22 -08:00
|
|
|
|
|
|
|
|
|
|
foreach (var widget in movementControlsContainer.DisableableWidgets)
|
|
|
|
|
|
{
|
2017-02-23 16:30:00 -08:00
|
|
|
|
widget?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
2016-01-13 07:39:22 -08:00
|
|
|
|
}
|
2017-02-27 13:26:33 -08:00
|
|
|
|
movementControlsContainer?.jogControls.SetEnabledLevels(false, false);
|
2016-01-13 07:39:22 -08:00
|
|
|
|
|
2015-04-08 15:20:10 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
2017-06-13 17:32:38 -07:00
|
|
|
|
case CommunicationStates.FinishedPrint:
|
|
|
|
|
|
case CommunicationStates.Connected:
|
2017-02-23 16:30:00 -08:00
|
|
|
|
movementControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
|
|
|
|
|
fanControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
|
|
|
|
|
macroControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
|
|
|
|
|
actionControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
|
|
|
|
|
tuningAdjustmentControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
2017-08-06 19:22:47 -07:00
|
|
|
|
calibrationControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
2016-01-13 07:39:22 -08:00
|
|
|
|
|
|
|
|
|
|
foreach (var widget in movementControlsContainer.DisableableWidgets)
|
|
|
|
|
|
{
|
2017-02-23 16:30:00 -08:00
|
|
|
|
widget?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
2016-01-13 07:39:22 -08:00
|
|
|
|
}
|
2017-02-27 13:26:33 -08:00
|
|
|
|
movementControlsContainer?.jogControls.SetEnabledLevels(false, true);
|
2015-04-08 15:20:10 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
2017-06-13 17:32:38 -07:00
|
|
|
|
case CommunicationStates.PrintingFromSd:
|
2017-02-23 16:30:00 -08:00
|
|
|
|
movementControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.ConfigOnly);
|
|
|
|
|
|
fanControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
|
|
|
|
|
macroControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.ConfigOnly);
|
|
|
|
|
|
actionControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
|
|
|
|
|
tuningAdjustmentControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
2017-08-06 19:22:47 -07:00
|
|
|
|
calibrationControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
2015-04-08 15:20:10 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
2017-06-13 17:32:38 -07:00
|
|
|
|
case CommunicationStates.PreparingToPrint:
|
|
|
|
|
|
case CommunicationStates.Printing:
|
2017-06-13 17:22:49 -07:00
|
|
|
|
switch (PrinterConnection.Instance.PrintingState)
|
2015-04-08 15:20:10 -07:00
|
|
|
|
{
|
2017-06-13 17:32:38 -07:00
|
|
|
|
case DetailedPrintingState.HomingAxis:
|
|
|
|
|
|
case DetailedPrintingState.HeatingBed:
|
|
|
|
|
|
case DetailedPrintingState.HeatingExtruder:
|
|
|
|
|
|
case DetailedPrintingState.Printing:
|
2017-02-23 16:30:00 -08:00
|
|
|
|
fanControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
|
|
|
|
|
macroControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.ConfigOnly);
|
|
|
|
|
|
actionControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
|
|
|
|
|
tuningAdjustmentControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
2017-08-06 19:22:47 -07:00
|
|
|
|
calibrationControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
2016-01-13 07:39:22 -08:00
|
|
|
|
|
2017-08-06 19:22:47 -07:00
|
|
|
|
foreach (var widget in movementControlsContainer.DisableableWidgets)
|
2016-01-13 07:39:22 -08:00
|
|
|
|
{
|
2017-02-23 16:30:00 -08:00
|
|
|
|
widget?.SetEnableLevel(DisableableWidget.EnableLevel.Disabled);
|
2016-01-13 07:39:22 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-02-27 13:26:33 -08:00
|
|
|
|
movementControlsContainer?.jogControls.SetEnabledLevels(true, false);
|
2015-04-08 15:20:10 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
2017-06-13 17:32:38 -07:00
|
|
|
|
case CommunicationStates.Paused:
|
2017-02-23 16:30:00 -08:00
|
|
|
|
movementControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
|
|
|
|
|
fanControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
|
|
|
|
|
macroControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
|
|
|
|
|
actionControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
|
|
|
|
|
tuningAdjustmentControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
2017-08-06 19:22:47 -07:00
|
|
|
|
calibrationControlsContainer?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
2016-01-13 07:39:22 -08:00
|
|
|
|
|
|
|
|
|
|
foreach (var widget in movementControlsContainer.DisableableWidgets)
|
|
|
|
|
|
{
|
2017-02-23 16:30:00 -08:00
|
|
|
|
widget?.SetEnableLevel(DisableableWidget.EnableLevel.Enabled);
|
2016-01-13 07:39:22 -08:00
|
|
|
|
}
|
2017-02-27 13:26:33 -08:00
|
|
|
|
movementControlsContainer?.jogControls.SetEnabledLevels(false, true);
|
2016-01-13 07:39:22 -08:00
|
|
|
|
|
2015-04-08 15:20:10 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-02-23 12:43:37 -08:00
|
|
|
|
}
|