Saxonite 1.2.11.3. Sandtrap.
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>Sarand.Net.Mobile</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Essentials" Version="1.8.1" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2622" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SacsStandardBase\SacsStandardBase.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,50 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.App
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaxApplication : Application
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SaxApplication ()
|
||||
{
|
||||
// Xamarin Essentials version tracking.
|
||||
VersionTracking.Track();
|
||||
|
||||
// Log environment.
|
||||
SaLogger.Debug("AppInfo.AppName: " + AppInfo.Name);
|
||||
SaLogger.Debug("AppInfo.PackageName: " + AppInfo.PackageName);
|
||||
SaLogger.Debug("AppInfo.Version: " + AppInfo.VersionString);
|
||||
SaLogger.Debug("AppInfo.Build: " + AppInfo.BuildString);
|
||||
SaLogger.Debug("DeviceWidth: " + DeviceWidth);
|
||||
SaLogger.Debug("DeviceHeight: " + DeviceHeight);
|
||||
SaLogger.Debug("DeviceDensity: " + DeviceDisplay.MainDisplayInfo.Density);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
// Device screen size and orientation.
|
||||
public static bool Landscape => DeviceWidth > DeviceHeight;
|
||||
public static double DeviceWidth => DeviceDisplay.MainDisplayInfo.Width;
|
||||
public static double DeviceHeight => DeviceDisplay.MainDisplayInfo.Height;
|
||||
public static double MinDeviceDimension => Math.Min(DeviceWidth, DeviceHeight);
|
||||
public static double MaxDeviceDimension => Math.Max(DeviceWidth, DeviceHeight);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Base
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxComponents
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private bool readOnly = false;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxComponents ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public bool ReadOnly
|
||||
{
|
||||
get { return readOnly; }
|
||||
set { if (readOnly == value) return; readOnly = value; SetControlsReadOnly(); }
|
||||
}
|
||||
public bool Changed { get; protected set; } = false;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n f i g u r e C o m p o n e n t s
|
||||
//-------------------------------------------------------------------
|
||||
protected virtual void ConfigureComponents ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l A c t i v i t y
|
||||
//-------------------------------------------------------------------
|
||||
protected virtual void SetControlActivity ()
|
||||
{
|
||||
}
|
||||
protected virtual void SetControlsReadOnly ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Controls
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxButton : Button
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxButton ()
|
||||
{
|
||||
DefaultFontSize = FontSize;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public double DefaultFontSize { get; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Layouts;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Controls
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxDatePicker : SaxContentView
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private bool allowInvalidDate = false;
|
||||
private bool invalidDate = true;
|
||||
private DateTime previousDate = DateTime.MinValue;
|
||||
private SaxStackLayout controlLayout = new SaxStackLayout() { Orientation=StackOrientation.Horizontal, HorizontalOptions=LayoutOptions.Fill };
|
||||
private DatePicker pickerDate = new DatePicker() { IsVisible = false };
|
||||
private SaxEntry entryDate = new SaxEntry() { HorizontalOptions=LayoutOptions.FillAndExpand, VerticalOptions=LayoutOptions.Fill };
|
||||
private SaxLabel labelResetDate = new SaxLabel() { Text="X", FontAttributes=FontAttributes.Bold, TextColor=Color.Red, HorizontalOptions=LayoutOptions.Center, VerticalTextAlignment=TextAlignment.Center };
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxDatePicker ()
|
||||
{
|
||||
// Initialise controls.
|
||||
// Date picker. Hidden but used to display calendar.
|
||||
DefaultFontSize = pickerDate.FontSize;
|
||||
pickerDate.Format = "dd-MMM-yyyy";
|
||||
pickerDate.DateSelected += PickerDate_DateSelected;
|
||||
// Date display entry.
|
||||
entryDate.FontSize = pickerDate.FontSize;
|
||||
entryDate.FontFamily = pickerDate.FontFamily;
|
||||
entryDate.FontAttributes = pickerDate.FontAttributes;
|
||||
entryDate.TextColor = pickerDate.TextColor;
|
||||
entryDate.Focused += EntryDate_Focused;
|
||||
// 'Reset' date label - to invalidate the date value.
|
||||
labelResetDate.FontSize = pickerDate.FontSize;
|
||||
labelResetDate.FontFamily = pickerDate.FontFamily;
|
||||
|
||||
// 'Reset' label tap gesture.
|
||||
var tapGestureRecognizer = new TapGestureRecognizer();
|
||||
tapGestureRecognizer.Tapped += LabelValidDate_Tapped;
|
||||
labelResetDate.GestureRecognizers.Add(tapGestureRecognizer);
|
||||
|
||||
// Initialise layout.
|
||||
Content = controlLayout;
|
||||
controlLayout.Children.Add(pickerDate);
|
||||
controlLayout.Children.Add(entryDate);
|
||||
controlLayout.Children.Add(labelResetDate);
|
||||
|
||||
RefreshDateDisplay();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
// Configuration.
|
||||
public Boolean AllowInvalid
|
||||
{
|
||||
get { return allowInvalidDate; }
|
||||
set
|
||||
{
|
||||
if (allowInvalidDate = value) return;
|
||||
allowInvalidDate = value;
|
||||
if (!allowInvalidDate) invalidDate = false;
|
||||
RefreshDateDisplay();
|
||||
}
|
||||
}
|
||||
public string Format
|
||||
{
|
||||
get { return pickerDate.Format; }
|
||||
set
|
||||
{
|
||||
if (pickerDate.Format.Equals(value)) return;
|
||||
pickerDate.Format = value;
|
||||
}
|
||||
}
|
||||
public DateTime MinimumDate
|
||||
{
|
||||
get { return pickerDate.MinimumDate; }
|
||||
set { pickerDate.MinimumDate = value; }
|
||||
}
|
||||
public DateTime MaximumDate
|
||||
{
|
||||
get { return pickerDate.MaximumDate; }
|
||||
set { pickerDate.MaximumDate = value; }
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
// Date value.
|
||||
public DateTime Date
|
||||
{
|
||||
get
|
||||
{
|
||||
if (invalidDate) return DateTime.MinValue;
|
||||
return pickerDate.Date;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Date.Equals(value)) return;
|
||||
if (!DateUtil.IsValid(value))
|
||||
{
|
||||
invalidDate = true;
|
||||
pickerDate.Date = DateTime.Today;
|
||||
}
|
||||
else
|
||||
{
|
||||
invalidDate = false;
|
||||
pickerDate.Date = value;
|
||||
}
|
||||
previousDate = value;
|
||||
}
|
||||
}
|
||||
public String FormattedDate { get { return !invalidDate ? DateUtil.Format(Date, pickerDate.Format) : ""; } }
|
||||
//-------------------------------------------------------------------
|
||||
// Font.
|
||||
public double DefaultFontSize { get; }
|
||||
public double FontSize
|
||||
{
|
||||
get { return pickerDate.FontSize; }
|
||||
set
|
||||
{
|
||||
if (pickerDate.FontSize == value) return;
|
||||
pickerDate.FontSize = value;
|
||||
entryDate.FontSize = value;
|
||||
}
|
||||
}
|
||||
public String FontFamily
|
||||
{
|
||||
get { return pickerDate.FontFamily; }
|
||||
set
|
||||
{
|
||||
if (pickerDate.FontFamily == value) return;
|
||||
pickerDate.FontFamily = value;
|
||||
entryDate.FontFamily = value;
|
||||
}
|
||||
}
|
||||
public FontAttributes FontAttributes
|
||||
{
|
||||
get { return pickerDate.FontAttributes; }
|
||||
set
|
||||
{
|
||||
if (pickerDate.FontAttributes == value) return;
|
||||
pickerDate.FontAttributes = value;
|
||||
entryDate.FontAttributes = value;
|
||||
}
|
||||
}
|
||||
public Color TextColor
|
||||
{
|
||||
get { return pickerDate.TextColor; }
|
||||
set
|
||||
{
|
||||
if (pickerDate.TextColor == value) return;
|
||||
pickerDate.TextColor = value;
|
||||
entryDate.TextColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Utilities.
|
||||
private void RefreshDateDisplay()
|
||||
{
|
||||
if (allowInvalidDate)
|
||||
{
|
||||
pickerDate.IsVisible = false;
|
||||
entryDate.IsVisible = true;
|
||||
labelResetDate.IsVisible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pickerDate.IsVisible = true;
|
||||
entryDate.IsVisible = false;
|
||||
labelResetDate.IsVisible = false;
|
||||
}
|
||||
String dateValue = "";
|
||||
if (!invalidDate)
|
||||
dateValue = DateUtil.Format(Date, pickerDate.Format);
|
||||
entryDate.Text = dateValue;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
private void PickerDate_DateSelected (object sender, DateChangedEventArgs e)
|
||||
{
|
||||
// Date has changed in control.
|
||||
invalidDate = !DateUtil.IsValid(e.NewDate);
|
||||
RefreshDateDisplay();
|
||||
if (DateSelected != null) DateSelected.Invoke(sender, e);
|
||||
}
|
||||
public event EventHandler<DateChangedEventArgs> DateSelected;
|
||||
//-------------------------------------------------------------------
|
||||
private void EntryDate_Focused (object sender, FocusEventArgs e)
|
||||
{
|
||||
// Control has gained focus.
|
||||
entryDate.Unfocus();
|
||||
pickerDate.Focus();
|
||||
invalidDate = false;
|
||||
RefreshDateDisplay();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
private void LabelValidDate_Tapped (object sender, EventArgs e)
|
||||
{
|
||||
// 'Valid' label tapped.
|
||||
if (invalidDate) return;
|
||||
invalidDate = true;
|
||||
DateTime oldDate = previousDate;
|
||||
RefreshDateDisplay();
|
||||
if (DateSelected != null) DateSelected.Invoke(sender, new DateChangedEventArgs(oldDate, Date));
|
||||
previousDate = Date;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Layouts;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Controls
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxDateTimePicker : SaxContentView
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
// Control layout.
|
||||
private SaxStackLayout layoutControl = new SaxStackLayout() { Orientation = StackOrientation.Horizontal };
|
||||
private SaxDatePicker pickerDate = new SaxDatePicker();
|
||||
private SaxLabel labelTimePrefix = new SaxLabel();
|
||||
private SaxTimePicker pickerTime = new SaxTimePicker();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxDateTimePicker ()
|
||||
{
|
||||
DefaultFontSize = pickerDate.FontSize;
|
||||
|
||||
// Configure components.
|
||||
Content = layoutControl;
|
||||
layoutControl.Children.Add(pickerDate);
|
||||
layoutControl.Children.Add(pickerTime);
|
||||
|
||||
// Control events.
|
||||
pickerDate.DateSelected += PickerDate_DateSelected;
|
||||
pickerTime.TimeChanged += PickerTime_TimeChanged;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public string DateFormat
|
||||
{
|
||||
get { return pickerDate.Format; }
|
||||
set
|
||||
{
|
||||
if (pickerDate.Format.Equals(value)) return;
|
||||
pickerDate.Format = value;
|
||||
}
|
||||
}
|
||||
public DateTime MinimumDate
|
||||
{
|
||||
get { return pickerDate.MinimumDate; }
|
||||
set { pickerDate.MinimumDate = value; }
|
||||
}
|
||||
public DateTime MaximumDate
|
||||
{
|
||||
get { return pickerDate.MaximumDate; }
|
||||
set { pickerDate.MaximumDate = value; }
|
||||
}
|
||||
public string TimeFormat
|
||||
{
|
||||
get { return pickerTime.Format; }
|
||||
set
|
||||
{
|
||||
if (pickerTime.Format.Equals(value)) return;
|
||||
pickerTime.Format = value;
|
||||
}
|
||||
}
|
||||
// Control value.
|
||||
public DateTime DateTime
|
||||
{
|
||||
get { return pickerDate.Date.Date + pickerTime.Time; }
|
||||
set
|
||||
{
|
||||
if (DateTime.CompareTo(value) == 0) return;
|
||||
pickerDate.Date = value.Date;
|
||||
pickerTime.Time = value - value.Date;
|
||||
}
|
||||
}
|
||||
public String DateTimeDelim { get; set; } = " ";
|
||||
public String FormattedDateTime { get { return pickerDate.FormattedDate + DateTimeDelim + pickerTime.FormattedTime; } }
|
||||
// Styling.
|
||||
public double DefaultFontSize { get; }
|
||||
public double FontSize
|
||||
{
|
||||
get { return pickerDate.FontSize; }
|
||||
set { if (pickerDate.FontSize == value) return; pickerDate.FontSize = value; pickerTime.FontSize = value; labelTimePrefix.FontSize = value; }
|
||||
}
|
||||
/// <summary>Amount of space between date and time pickers.</summary>
|
||||
public double ControlSpacing
|
||||
{
|
||||
get { return layoutControl.Spacing; }
|
||||
set { if (layoutControl.Spacing == value) return; layoutControl.Spacing = value; }
|
||||
}
|
||||
public String TimePickerPrefixText
|
||||
{
|
||||
get { return labelTimePrefix.Text; }
|
||||
set { value = StringUtil.TrimAll(value); if (labelTimePrefix.Text.Equals(value)) return; labelTimePrefix.Text = value; ConfigureComponents(); }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n f i g u r e C o m p o n e n t s
|
||||
//-------------------------------------------------------------------
|
||||
protected override void ConfigureComponents ()
|
||||
{
|
||||
base.ConfigureComponents();
|
||||
|
||||
// Time Picker prefix label text.
|
||||
if (!StringUtil.IsEmpty(TimePickerPrefixText))
|
||||
{
|
||||
// Label has text - ensure label is in the layout.
|
||||
if (!layoutControl.Children.Contains(labelTimePrefix))
|
||||
{
|
||||
// Label will be inserted before the time picker.
|
||||
int insertIdx = layoutControl.Children.IndexOf(pickerTime);
|
||||
layoutControl.Children.Insert(insertIdx, labelTimePrefix);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Blank label text - remove label from layout.
|
||||
if (layoutControl.Children.Contains(labelTimePrefix))
|
||||
layoutControl.Children.Remove(labelTimePrefix);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l A c t i v i t y
|
||||
//-------------------------------------------------------------------
|
||||
protected override void SetControlActivity ()
|
||||
{
|
||||
base.SetControlActivity();
|
||||
}
|
||||
protected override void SetControlsReadOnly ()
|
||||
{
|
||||
base.SetControlsReadOnly();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
private void PickerDate_DateSelected (object sender, DateChangedEventArgs e)
|
||||
{
|
||||
if (DateSelected != null) DateSelected.Invoke(sender, e);
|
||||
}
|
||||
public event EventHandler<DateChangedEventArgs> DateSelected;
|
||||
//-------------------------------------------------------------------
|
||||
private void PickerTime_TimeChanged (object sender, SaxTimePicker.TimeChangedEventArgs e)
|
||||
{
|
||||
if (TimeChanged != null) TimeChanged.Invoke(sender, e);
|
||||
}
|
||||
public event EventHandler<SaxTimePicker.TimeChangedEventArgs> TimeChanged;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Controls
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxEditor : Editor
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private bool trimTextOnCompletion = true;
|
||||
private int NumberOfLinesPrevious = 0;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxEditor ()
|
||||
{
|
||||
DefaultFontSize = FontSize;
|
||||
Text = "";
|
||||
TextChanged += SaxEditor_TextChanged;
|
||||
Completed += SaxEditor_Completed;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public double DefaultFontSize { get; }
|
||||
public bool TrimText
|
||||
{
|
||||
get { return trimTextOnCompletion; }
|
||||
set
|
||||
{
|
||||
if (trimTextOnCompletion == value) return;
|
||||
trimTextOnCompletion = value;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
// Key Press event is not supported directly in Xamarin.
|
||||
// Requires O/S specific implementation.
|
||||
// See: Sarand.LogisticsMgr.Mobile.Droid.Forms.Renderers.SlmEditorRenderer
|
||||
public void OnKeyPress_Enter ()
|
||||
{
|
||||
// Resize control based on entered text.
|
||||
InvalidateMeasure();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
private void SaxEditor_TextChanged (object sender, TextChangedEventArgs e)
|
||||
{
|
||||
// If the number of lines of text has changed, resize the control.
|
||||
int NumberOfLines = StringUtil.EmptyOnNull(Text).Split('\n').Length;
|
||||
if (NumberOfLines != NumberOfLinesPrevious)
|
||||
// Resize control based on entered text.
|
||||
InvalidateMeasure();
|
||||
NumberOfLinesPrevious = NumberOfLines;
|
||||
}
|
||||
private void SaxEditor_Completed (object sender, EventArgs e)
|
||||
{
|
||||
if (trimTextOnCompletion)
|
||||
Text = Text.Trim();
|
||||
// Resize control based on entered text.
|
||||
InvalidateMeasure();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Controls
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxEntry : Entry
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public enum TextCaseType
|
||||
{
|
||||
Normal,
|
||||
Upper,
|
||||
Lower,
|
||||
Title
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private bool trimTextOnCompletion = true;
|
||||
private TextInfo textInfo = CultureInfo.CurrentCulture.TextInfo;
|
||||
private TextCaseType textCase = TextCaseType.Normal;
|
||||
private bool numericOnly = false;
|
||||
private byte decimals = 0;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxEntry ()
|
||||
{
|
||||
DefaultFontSize = FontSize;
|
||||
TextChanged += SaxEntry_TextChanged;
|
||||
Completed += SaxEntry_Completed;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public bool TrimText
|
||||
{
|
||||
get { return trimTextOnCompletion; }
|
||||
set
|
||||
{
|
||||
if (trimTextOnCompletion == value) return;
|
||||
trimTextOnCompletion = value;
|
||||
}
|
||||
}
|
||||
public double DefaultFontSize { get; }
|
||||
public TextCaseType TextCase
|
||||
{
|
||||
get { return textCase; }
|
||||
set
|
||||
{
|
||||
if (textCase == value) return;
|
||||
textCase = value;
|
||||
FormatText();
|
||||
}
|
||||
}
|
||||
public bool NumericOnly
|
||||
{
|
||||
get { return numericOnly; }
|
||||
set
|
||||
{
|
||||
if (numericOnly == value) return;
|
||||
numericOnly = value;
|
||||
Keyboard = Keyboard.Numeric;
|
||||
FormatText();
|
||||
}
|
||||
}
|
||||
public byte Decimals
|
||||
{
|
||||
get { return decimals; }
|
||||
set
|
||||
{
|
||||
if (numericOnly && decimals == value) return;
|
||||
numericOnly = true;
|
||||
decimals = value;
|
||||
Keyboard = Keyboard.Numeric;
|
||||
FormatText();
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// F o r m a t T e x t
|
||||
//-------------------------------------------------------------------
|
||||
private void FormatText (bool trimText = false)
|
||||
{
|
||||
String fn = GetType().Name + ".FormatText";
|
||||
String originalText = Text;
|
||||
String formattedText = originalText;
|
||||
if (StringUtil.IsEmpty(formattedText)) return;
|
||||
if (trimText)
|
||||
formattedText = StringUtil.TrimAll(formattedText);
|
||||
|
||||
if (numericOnly)
|
||||
{
|
||||
if (decimals > 0)
|
||||
{
|
||||
decimal value = StringUtil.ToDecimal(formattedText);
|
||||
if (value != 0.0m)
|
||||
formattedText = value.ToString("N" + decimals);
|
||||
else if (!formattedText.Equals("0"))
|
||||
formattedText = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
long value = StringUtil.ToLong(formattedText);
|
||||
if (value != 0)
|
||||
formattedText = value.ToString();
|
||||
else if (!formattedText.Equals("0"))
|
||||
formattedText = "";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (textCase == TextCaseType.Upper)
|
||||
formattedText = textInfo.ToUpper(formattedText);
|
||||
else if (textCase == TextCaseType.Lower)
|
||||
formattedText = textInfo.ToLower(formattedText);
|
||||
else if (textCase == TextCaseType.Title)
|
||||
formattedText =
|
||||
StringUtil.ToTitleCase(formattedText, textInfo);
|
||||
}
|
||||
|
||||
if (!originalText.Equals(formattedText))
|
||||
{
|
||||
SaLogger.Debug(fn + " Text: " + originalText + ". Formatted: " + formattedText);
|
||||
Text = formattedText;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
private void SaxEntry_TextChanged (object sender, TextChangedEventArgs e)
|
||||
{
|
||||
FormatText();
|
||||
}
|
||||
private void SaxEntry_Completed (object sender, EventArgs e)
|
||||
{
|
||||
FormatText(trimTextOnCompletion);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Controls
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxImageButton : ImageButton
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxImageButton ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Controls
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxLabel : Label
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxLabel ()
|
||||
{
|
||||
DefaultFontSize = FontSize;
|
||||
Text = "";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public double DefaultFontSize { get; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Controls
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxPicker : Picker
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public class SaxPickerItem
|
||||
{
|
||||
public SysId Id { get; set; } = new SysId();
|
||||
public String Code { get; set; } = "";
|
||||
public String Caption { get; set; } = "";
|
||||
public Object Object { get; set; }
|
||||
public override string ToString ()
|
||||
{
|
||||
return Caption;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private readonly List<SaxPickerItem> pickerItems = new List<SaxPickerItem>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxPicker ()
|
||||
{
|
||||
DefaultFontSize = FontSize;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public double DefaultFontSize { get; }
|
||||
public bool BeingPopulated { get; protected set; } = false;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P o p u l a t e I t e m s
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Does the list contain an item with the same Id.
|
||||
/// <para>NB Invalid Id values are matched.</para>
|
||||
/// </summary>
|
||||
public bool ContainsItemId (SysId id)
|
||||
{
|
||||
return pickerItems.Exists(item => SysId.ToInt(item.Id) == SysId.ToInt(id));
|
||||
}
|
||||
/// <summary>
|
||||
/// Does the list contain an item with the same code.
|
||||
/// <para>NB Codes are case-insensitive.</para>
|
||||
/// </summary>
|
||||
public bool ContainsItemCode (String code)
|
||||
{
|
||||
return pickerItems.Exists(item => item.Code.EqualsCI(code));
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Remove all items from the picker.</summary>
|
||||
public void ClearItems ()
|
||||
{
|
||||
Items.Clear();
|
||||
ItemsSource = null;
|
||||
pickerItems.Clear();
|
||||
}
|
||||
/// <summary>Replace existing picker item list.</summary>
|
||||
public void SetItems (List<SaxPickerItem> pickerItems)
|
||||
{
|
||||
ClearItems();
|
||||
this.pickerItems.AddRange(pickerItems);
|
||||
RefreshPickerItems();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Add an item identified by a SysId value.
|
||||
/// <para>NB Fails if an item already exists with the same id.</para>
|
||||
/// </summary>
|
||||
public bool AddItem (SysId id, String caption)
|
||||
{
|
||||
if (ContainsItemId(id)) return false;
|
||||
pickerItems.Add(new SaxPickerItem() { Id = id, Caption = caption });
|
||||
RefreshPickerItems();
|
||||
return ContainsItemId(id);
|
||||
}
|
||||
/// <summary>
|
||||
/// Add an item identified by a code value.
|
||||
/// <para>NB Fails if an item already exists with the same case-insensitive code.</para>
|
||||
/// </summary>
|
||||
public bool AddItem (String code, String caption)
|
||||
{
|
||||
if (ContainsItemCode(code)) return false;
|
||||
pickerItems.Add(new SaxPickerItem() { Code = code, Caption = caption });
|
||||
RefreshPickerItems();
|
||||
return ContainsItemCode(code);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
private void RefreshPickerItems ()
|
||||
{
|
||||
//SetBinding(Picker.ItemsSourceProperty, BindableProperty.Create());
|
||||
//ItemDisplayBinding = new Binding("Caption");
|
||||
// Picker items doesn't automatically keep up to date with teh ItemsSource list.
|
||||
// So clear it and reset to force the refresh.
|
||||
ItemsSource = null;
|
||||
ItemsSource = pickerItems;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// I t e m S e l e c t i o n
|
||||
//-------------------------------------------------------------------
|
||||
public SaxPickerItem SelectedPickerItem
|
||||
{
|
||||
get
|
||||
{
|
||||
object selectedItem = SelectedItem;
|
||||
if (selectedItem == null || !(selectedItem is SaxPickerItem)) return null;
|
||||
return (selectedItem as SaxPickerItem);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (SelectedPickerItem == value) return;
|
||||
if (ItemsSource == null || !ItemsSource.Contains(value)) return;
|
||||
base.SelectedItem = value;
|
||||
}
|
||||
}
|
||||
public SysId SelectedItemId
|
||||
{
|
||||
get
|
||||
{
|
||||
SaxPickerItem selectedPickerItem = SelectedPickerItem;
|
||||
return selectedPickerItem != null ? selectedPickerItem.Id : new SysId();
|
||||
}
|
||||
set
|
||||
{
|
||||
SelectedPickerItem = pickerItems.Find(item => item.Id.Equals(value));
|
||||
}
|
||||
}
|
||||
public String SelectedItemCode
|
||||
{
|
||||
get
|
||||
{
|
||||
SaxPickerItem selectedPickerItem = SelectedPickerItem;
|
||||
return selectedPickerItem != null ? selectedPickerItem.Code : "";
|
||||
}
|
||||
set
|
||||
{
|
||||
SelectedPickerItem = pickerItems.Find(item => item.Code.EqualsCI(value));
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
// Picker population completed.
|
||||
public class PopulatedEventArgs : EventArgs { }
|
||||
public delegate void PopulatedEventHandler (object sender, PopulatedEventArgs e);
|
||||
/// <summary>Picker population completed event handler.</summary>
|
||||
public event PopulatedEventHandler Populated;
|
||||
protected void InvokePopulatedEvent ()
|
||||
{
|
||||
if (Populated != null) Populated.Invoke(this, new PopulatedEventArgs() { });
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Layouts;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Panels;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Controls
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxTabControl : ContentView
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private readonly List<SaxTabPanel> tabPanels = new List<SaxTabPanel>();
|
||||
private short currentTabIdx = -1;
|
||||
// Main layout to host header and body.
|
||||
private SaxStackLayout mainLayout = new SaxStackLayout() { Orientation = StackOrientation.Vertical };
|
||||
// Header layout - horizontal row.
|
||||
private SaxFlexLayout headerPanel = new SaxFlexLayout() { Direction = FlexDirection.Row, AlignItems = FlexAlignItems.Center, JustifyContent = FlexJustify.Start, HorizontalOptions = LayoutOptions.Start };
|
||||
// Body - Content view to host tab panel.
|
||||
private SaxContentView bodyPanel = new SaxContentView();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxTabControl ()
|
||||
{
|
||||
// Main layout - vertical stack with two rows.
|
||||
// 1. Header - tab panel captions.
|
||||
// 2. Body - current tab panel.
|
||||
VerticalOptions = LayoutOptions.FillAndExpand;
|
||||
//BackgroundColor = Color.LightSkyBlue;
|
||||
mainLayout.VerticalOptions = LayoutOptions.FillAndExpand;
|
||||
mainLayout.Spacing = 2.0;
|
||||
Content = mainLayout;
|
||||
|
||||
// Header panel - tab captions.
|
||||
//headerPanel.HorizontalOptions = LayoutOptions.Fill;
|
||||
mainLayout.Children.Add(headerPanel);
|
||||
|
||||
// Default label font size.
|
||||
DefaultHeaderFontSize = new Label().FontSize;
|
||||
HeaderFontSize = DefaultHeaderFontSize;
|
||||
|
||||
// Body panel.
|
||||
bodyPanel.HorizontalOptions = LayoutOptions.Fill;
|
||||
bodyPanel.VerticalOptions = LayoutOptions.FillAndExpand;
|
||||
bodyPanel.BackgroundColor = Color.LightYellow;
|
||||
mainLayout.Children.Add(bodyPanel);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
// Header.
|
||||
public Color HeaderBackgroundColor { get { return headerPanel.BackgroundColor; } set { headerPanel.BackgroundColor = value; } }
|
||||
public Color CaptionBackgroundColor { get; set; } = Color.Transparent;
|
||||
public double DefaultHeaderFontSize { get; }
|
||||
public double HeaderFontSize { get; set; }
|
||||
public double HeaderMarginBottom
|
||||
{
|
||||
get { return mainLayout.Spacing; }
|
||||
set { if (mainLayout.Spacing == value) return; mainLayout.Spacing = value; }
|
||||
}
|
||||
public Thickness HeaderPadding
|
||||
{
|
||||
get { return mainLayout.Padding; }
|
||||
set { if (mainLayout.Padding == value) return; mainLayout.Padding = value; }
|
||||
}
|
||||
public Thickness HeaderCaptionPadding { get; set; } = new Thickness(12.0, 4.0);
|
||||
public double HeaderCaptionSpacing { get; set; } = 4.0;
|
||||
// Tab panels.
|
||||
public Color BodyBackgroundColor { get { return bodyPanel.BackgroundColor; } set { bodyPanel.BackgroundColor = value; } }
|
||||
public int PanelCount { get { return tabPanels.Count; } }
|
||||
public short TabPanelIndex
|
||||
{
|
||||
get { return currentTabIdx; }
|
||||
set { ChangeTabPanel(value); }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// T a b P a n e l s
|
||||
//-------------------------------------------------------------------
|
||||
public void ClearPanels ()
|
||||
{
|
||||
tabPanels.Clear();
|
||||
RefreshLayout();
|
||||
}
|
||||
public void AddPanel (String caption, SaxContentView panel)
|
||||
{
|
||||
AddPanel(new SaxTabPanel(caption, panel));
|
||||
}
|
||||
public void AddPanel (SaxTabPanel tabPanel)
|
||||
{
|
||||
AddPanels(new List<SaxTabPanel>() { tabPanel });
|
||||
}
|
||||
public void AddPanels (IEnumerable<SaxTabPanel> tabPanels)
|
||||
{
|
||||
this.tabPanels.AddRange(tabPanels);
|
||||
RefreshLayout();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// R e f r e s h L a y o u t
|
||||
//-------------------------------------------------------------------
|
||||
private void RefreshLayout ()
|
||||
{
|
||||
// Clear existing components.
|
||||
headerPanel.Children.Clear();
|
||||
bodyPanel.Content = null;
|
||||
|
||||
// Add each Tab panel in turn.
|
||||
for (short tabPanelIdx = 0; tabPanelIdx < tabPanels.Count; tabPanelIdx++)
|
||||
{
|
||||
short tabPanelIdx_Local = tabPanelIdx; // Loop closure.
|
||||
SaxTabPanel tabPanel = tabPanels[tabPanelIdx];
|
||||
|
||||
// Header caption.
|
||||
SaxContentView captionPanel = new SaxContentView()
|
||||
{
|
||||
Padding = HeaderCaptionPadding,
|
||||
BackgroundColor = CaptionBackgroundColor,
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand,
|
||||
VerticalOptions = LayoutOptions.FillAndExpand
|
||||
};
|
||||
if (tabPanelIdx > 0)
|
||||
captionPanel.Margin = new Thickness(HeaderCaptionSpacing, 0, 0, 0);
|
||||
SaxLabel captionLabel = new SaxLabel()
|
||||
{
|
||||
Text = tabPanel.Caption,
|
||||
FontSize = HeaderFontSize
|
||||
};
|
||||
captionPanel.Content = captionLabel;
|
||||
headerPanel.Children.Add(captionPanel);
|
||||
|
||||
// Tap Gesture.
|
||||
var tapGestureRecognizer = new TapGestureRecognizer();
|
||||
tapGestureRecognizer.Tapped += (s, e) => { ChangeTabPanel(tabPanelIdx_Local); };
|
||||
captionPanel.GestureRecognizers.Add(tapGestureRecognizer);
|
||||
}
|
||||
// Current tab retains previous value if still valid (in panel range),
|
||||
// is restricted to the range 0 to number of panels - 1 if there are panels,
|
||||
// or -1 if no panels.
|
||||
currentTabIdx = (short)(tabPanels.Count > 0 ? Math.Max(0, Math.Min(tabPanels.Count - 1, currentTabIdx)) : -1);
|
||||
if (tabPanels.Count > 0)
|
||||
ChangeTabPanel(currentTabIdx);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C h a n g e T a b P a n e l
|
||||
//-------------------------------------------------------------------
|
||||
private void ChangeTabPanel (short tabPanelIdx)
|
||||
{
|
||||
// Validate requested panel index.
|
||||
if (tabPanelIdx < 0 || tabPanelIdx >= tabPanels.Count)
|
||||
throw new IndexOutOfRangeException("Tab panel index must be between 0 & " + (tabPanels.Count - 1) + ". Supplied value: " + tabPanelIdx);
|
||||
|
||||
// Highlight selected tab panel header caption.
|
||||
for (short headerPanelIdx = 0; headerPanelIdx < headerPanel.Children.Count; headerPanelIdx++)
|
||||
{
|
||||
View headerPanelView = headerPanel.Children[headerPanelIdx];
|
||||
Label headerPanelLabel = (headerPanelView as Label);
|
||||
if (headerPanelLabel == null && headerPanelView is ContentView)
|
||||
headerPanelLabel = ((headerPanelView as ContentView).Content as Label);
|
||||
if (headerPanelLabel != null)
|
||||
{
|
||||
if (headerPanelIdx == tabPanelIdx)
|
||||
headerPanelLabel.FontAttributes = FontAttributes.Bold;
|
||||
else headerPanelLabel.FontAttributes = FontAttributes.None;
|
||||
}
|
||||
}
|
||||
|
||||
// Display selected tab panel.
|
||||
bodyPanel.Content = tabPanels[tabPanelIdx];
|
||||
currentTabIdx = tabPanelIdx;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Controls
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxTimePicker : TimePicker
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxTimePicker ()
|
||||
{
|
||||
DefaultFontSize = FontSize;
|
||||
Format = "HH:mm";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public String FormattedTime { get { return DateUtil.Format(DateTime.Today + Time, Format); } }
|
||||
// Styling.
|
||||
public double DefaultFontSize { get; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
public class TimeChangedEventArgs : EventArgs { };
|
||||
public event EventHandler<TimeChangedEventArgs> TimeChanged;
|
||||
protected override void OnPropertyChanged ([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (propertyName.EqualsCI(TimePicker.TimeProperty.PropertyName))
|
||||
{
|
||||
base.OnPropertyChanged(propertyName);
|
||||
if (TimeChanged != null) TimeChanged.Invoke(this, new TimeChangedEventArgs());
|
||||
return;
|
||||
}
|
||||
base.OnPropertyChanged(propertyName);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Controls
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxWebView : WebView
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
public String html = "";
|
||||
private HtmlWebViewSource htmlSource;
|
||||
private UrlWebViewSource aboutBlankSource = new UrlWebViewSource() { Url = "about:blank" };
|
||||
// Managers.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxWebView ()
|
||||
{
|
||||
// Events.
|
||||
Navigating += WebView_Navigating;
|
||||
Navigated += WebView_Navigated;
|
||||
|
||||
// HTML source.
|
||||
htmlSource = new HtmlWebViewSource() { Html = html };
|
||||
Source = aboutBlankSource;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
// HTML Panel.
|
||||
public static String AppActionPrefix => "App:";
|
||||
public String Html
|
||||
{
|
||||
get { return html; }
|
||||
set
|
||||
{
|
||||
Source = aboutBlankSource;
|
||||
htmlSource.Html = null;
|
||||
html = value;
|
||||
htmlSource.Html = html;
|
||||
Source = htmlSource;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// N a v i g a t i o n
|
||||
//-------------------------------------------------------------------
|
||||
public class AppNavigatingEventArgs : EventArgs
|
||||
{
|
||||
public String AppAction { get; set; }
|
||||
}
|
||||
public delegate void AppNavigatingEventHandler (object sender, AppNavigatingEventArgs e);
|
||||
public event AppNavigatingEventHandler AppNavigating;
|
||||
private void OnAppNavigating (String appAction)
|
||||
{
|
||||
if (AppNavigating != null) AppNavigating.Invoke(this, new AppNavigatingEventArgs() { AppAction = appAction });
|
||||
}
|
||||
private String GetAppAction (String location)
|
||||
{
|
||||
if (!location.StartsWithCI(AppActionPrefix)) return "";
|
||||
return location.Right(location.Length - AppActionPrefix.Length);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
private void WebView_Navigating (object sender, WebNavigatingEventArgs e)
|
||||
{
|
||||
String appAction = GetAppAction(e.Url);
|
||||
SaLogger.Debug("SaxWebView_Navigating URL: "+e.Url+". App action: "+ appAction);
|
||||
if (!StringUtil.IsEmpty(appAction))
|
||||
{
|
||||
e.Cancel = true;
|
||||
OnAppNavigating(appAction);
|
||||
}
|
||||
}
|
||||
private void WebView_Navigated (object sender, WebNavigatedEventArgs e)
|
||||
{
|
||||
SaLogger.Debug("SaxWebView_Navigated URL: " + e.Url);
|
||||
String appAction = GetAppAction(e.Url);
|
||||
if (!StringUtil.IsEmpty(appAction))
|
||||
{
|
||||
Source = htmlSource;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Layouts
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxAbsoluteLayout : AbsoluteLayout
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxAbsoluteLayout ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Layouts
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxFlexLayout : FlexLayout
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxFlexLayout ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Layouts
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxGrid : Grid
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxGrid()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// G r i d E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnParentSet()
|
||||
{
|
||||
base.OnParentSet();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnPropertyChanging([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
base.OnPropertyChanging(propertyName);
|
||||
}
|
||||
protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
base.OnPropertyChanged(propertyName);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnAdded(View view)
|
||||
{
|
||||
base.OnAdded(view);
|
||||
}
|
||||
protected override void OnChildAdded(Element child)
|
||||
{
|
||||
base.OnChildAdded(child);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnRemoved(View view)
|
||||
{
|
||||
base.OnRemoved(view);
|
||||
}
|
||||
[Obsolete("OnChildRemoved(Element) is obsolete as of version 4.8.0. Please use OnChildRemoved(Element, int) instead.")]
|
||||
protected override void OnChildRemoved(Element child)
|
||||
{
|
||||
base.OnChildRemoved(child);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Layouts
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxStackLayout : StackLayout
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxStackLayout ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Layouts
|
||||
{
|
||||
//=======================================================================
|
||||
/// <summary>
|
||||
/// Wrapping columnar layout - to achieve resposive behaviour.
|
||||
/// <para>Layout which performs wrapping on the boundaries.</para>
|
||||
/// <para>Base Code -> https://forums.xamarin.com/discussion/comment/57486/#Comment_57486</para>
|
||||
/// <para> http://bit.ly/xf-custompanel</para>
|
||||
/// </summary>
|
||||
//=======================================================================
|
||||
public class SaxWrapLayout : Layout<View>
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Horizontal spacing between elements.</summary>
|
||||
public double SpacingX
|
||||
{
|
||||
get { return (double)GetValue(SpacingXProperty); }
|
||||
set { SetValue(SpacingXProperty, value); }
|
||||
}
|
||||
public static BindableProperty SpacingXProperty =
|
||||
BindableProperty.Create(
|
||||
nameof(SpacingX),
|
||||
typeof(double),
|
||||
typeof(SaxWrapLayout),
|
||||
default(double),
|
||||
defaultBindingMode: BindingMode.OneWay,
|
||||
propertyChanged: (bindable, oldvalue, newvalue) => ((SaxWrapLayout)bindable).InvalidateMeasure()
|
||||
);
|
||||
/// <summary>Vertical spacing between elements.</summary>
|
||||
public double SpacingY
|
||||
{
|
||||
get { return (double)GetValue(SpacingYProperty); }
|
||||
set { SetValue(SpacingYProperty, value); }
|
||||
}
|
||||
public static BindableProperty SpacingYProperty =
|
||||
BindableProperty.Create(
|
||||
nameof(SpacingY),
|
||||
typeof(double),
|
||||
typeof(SaxWrapLayout),
|
||||
default(double),
|
||||
defaultBindingMode: BindingMode.OneWay,
|
||||
propertyChanged: (bindable, oldvalue, newvalue) => ((SaxWrapLayout)bindable).InvalidateMeasure()
|
||||
);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Number of uniform columns in each row.</summary>
|
||||
public int UniformColumns
|
||||
{
|
||||
get { return (int)GetValue(UniformColumnsProperty); }
|
||||
set { SetValue(UniformColumnsProperty, value); }
|
||||
}
|
||||
public static BindableProperty UniformColumnsProperty =
|
||||
BindableProperty.Create(
|
||||
nameof(UniformColumns),
|
||||
typeof(int),
|
||||
typeof(SaxWrapLayout),
|
||||
default(int),
|
||||
defaultBindingMode: BindingMode.OneWay,
|
||||
propertyChanged: (bindable, oldvalue, newvalue) => ((SaxWrapLayout)bindable).InvalidateMeasure()
|
||||
);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Item height equals item width when UniformColums > 0</summary>
|
||||
public bool IsSquare
|
||||
{
|
||||
get { return (bool)GetValue(IsSquareProperty); }
|
||||
set { SetValue(IsSquareProperty, value); }
|
||||
}
|
||||
public static BindableProperty IsSquareProperty =
|
||||
BindableProperty.Create(
|
||||
nameof(IsSquare),
|
||||
typeof(bool),
|
||||
typeof(SaxWrapLayout),
|
||||
false,
|
||||
propertyChanged: (bindable, oldvalue, newvalue) => ((SaxWrapLayout)bindable).InvalidateMeasure()
|
||||
);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
protected override SizeRequest OnMeasure (double widthConstraint, double heightConstraint)
|
||||
{
|
||||
if (WidthRequest > 0)
|
||||
widthConstraint = Math.Min(widthConstraint, WidthRequest);
|
||||
if (HeightRequest > 0)
|
||||
heightConstraint = Math.Min(heightConstraint, HeightRequest);
|
||||
|
||||
double internalWidth = double.IsPositiveInfinity(widthConstraint) ? double.PositiveInfinity : Math.Max(0, widthConstraint);
|
||||
double internalHeight = double.IsPositiveInfinity(heightConstraint) ? double.PositiveInfinity : Math.Max(0, heightConstraint);
|
||||
|
||||
if (double.IsPositiveInfinity(widthConstraint) && double.IsPositiveInfinity(heightConstraint))
|
||||
{
|
||||
return new SizeRequest(Size.Zero, Size.Zero);
|
||||
}
|
||||
|
||||
return UniformColumns > 0 ? UniformMeasureAndLayout(internalWidth, internalHeight) :
|
||||
VariableMeasureAndLayout(internalWidth, internalHeight);
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
protected override void LayoutChildren (double x, double y, double width, double height)
|
||||
{
|
||||
if (UniformColumns > 0)
|
||||
UniformMeasureAndLayout(width, height, true, x, y);
|
||||
else
|
||||
VariableMeasureAndLayout(width, height, true, x, y);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private SizeRequest UniformMeasureAndLayout
|
||||
(double widthConstraint, double heightConstraint, bool doLayout = false, double x = 0, double y = 0)
|
||||
{
|
||||
double totalWidth = 0;
|
||||
double totalHeight = 0;
|
||||
double rowHeight = 0;
|
||||
double minWidth = 0;
|
||||
double minHeight = 0;
|
||||
double xPos = x;
|
||||
double yPos = y;
|
||||
|
||||
totalWidth = widthConstraint;
|
||||
var exceptedWidth = widthConstraint - (UniformColumns - 1) * SpacingX; //excepted spacing width
|
||||
|
||||
var columnsSize = exceptedWidth / UniformColumns;
|
||||
if (columnsSize < 1)
|
||||
{
|
||||
columnsSize = 1;
|
||||
}
|
||||
|
||||
foreach (var child in Children.Where(c => c.IsVisible))
|
||||
{
|
||||
|
||||
var size = child.Measure(widthConstraint, heightConstraint);
|
||||
var itemWidth = (double)columnsSize;
|
||||
var itemHeight = size.Request.Height;
|
||||
|
||||
if (IsSquare)
|
||||
{
|
||||
itemHeight = columnsSize;
|
||||
}
|
||||
|
||||
rowHeight = Math.Max(rowHeight, itemHeight + SpacingY);
|
||||
|
||||
minHeight = Math.Max(minHeight, itemHeight);
|
||||
minWidth = Math.Max(minWidth, itemWidth);
|
||||
|
||||
if (doLayout)
|
||||
{
|
||||
var region = new Rectangle(xPos, yPos, itemWidth, itemHeight);
|
||||
LayoutChildIntoBoundingRegion(child, region);
|
||||
}
|
||||
|
||||
xPos += itemWidth + SpacingX;
|
||||
|
||||
if (xPos + columnsSize - x > widthConstraint)
|
||||
{
|
||||
xPos = x;
|
||||
yPos += rowHeight;
|
||||
totalHeight += rowHeight;
|
||||
rowHeight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
totalHeight = Math.Max(totalHeight + rowHeight - SpacingY, 0);
|
||||
|
||||
return new SizeRequest(new Size(totalWidth, totalHeight), new Size(minWidth, minHeight));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private SizeRequest VariableMeasureAndLayout
|
||||
(double widthConstraint, double heightConstraint, bool doLayout = false, double x = 0, double y = 0)
|
||||
{
|
||||
double totalWidth = 0;
|
||||
double totalHeight = 0;
|
||||
double rowHeight = 0;
|
||||
double rowWidth = 0;
|
||||
double minWidth = 0;
|
||||
double minHeight = 0;
|
||||
double xPos = x;
|
||||
double yPos = y;
|
||||
|
||||
var visibleChildren = Children.Where(c => c.IsVisible).Select(c => new
|
||||
{
|
||||
child = c,
|
||||
size = c.Measure(widthConstraint, heightConstraint)
|
||||
});
|
||||
|
||||
var nextChildren = visibleChildren.Skip(1).ToList();
|
||||
nextChildren.Add(null); //make element count same
|
||||
|
||||
var zipChildren = visibleChildren.Zip(nextChildren, (c, n) => new { current = c, next = n });
|
||||
|
||||
foreach (var childBlock in zipChildren)
|
||||
{
|
||||
var child = childBlock.current.child;
|
||||
var size = childBlock.current.size;
|
||||
var itemWidth = size.Request.Width;
|
||||
var itemHeight = size.Request.Height;
|
||||
|
||||
rowHeight = Math.Max(rowHeight, itemHeight + SpacingY);
|
||||
rowWidth += itemWidth + SpacingX;
|
||||
|
||||
minHeight = Math.Max(minHeight, itemHeight);
|
||||
minWidth = Math.Max(minWidth, itemWidth);
|
||||
|
||||
if (doLayout)
|
||||
{
|
||||
var region = new Rectangle(xPos, yPos, itemWidth, itemHeight);
|
||||
LayoutChildIntoBoundingRegion(child, region);
|
||||
}
|
||||
|
||||
if (childBlock.next == null)
|
||||
{
|
||||
totalHeight += rowHeight;
|
||||
totalWidth = Math.Max(totalWidth, rowWidth);
|
||||
break;
|
||||
}
|
||||
|
||||
xPos += itemWidth + SpacingX;
|
||||
var nextWitdh = childBlock.next.size.Request.Width;
|
||||
|
||||
if (xPos + nextWitdh - x > widthConstraint)
|
||||
{
|
||||
xPos = x;
|
||||
yPos += rowHeight;
|
||||
totalHeight += rowHeight;
|
||||
totalWidth = Math.Max(totalWidth, rowWidth);
|
||||
rowHeight = 0;
|
||||
rowWidth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
totalWidth = Math.Max(totalWidth - SpacingX, 0);
|
||||
totalHeight = Math.Max(totalHeight - SpacingY, 0);
|
||||
|
||||
return new SizeRequest(new Size(totalWidth, totalHeight), new Size(minWidth, minHeight));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Pages
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaxContentPage : ContentPage
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SaxContentPage ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public abstract String MessageTitleDefault { get; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P o p u p M e s s a g e s
|
||||
//-------------------------------------------------------------------
|
||||
public enum AlertMode
|
||||
{
|
||||
OK,
|
||||
Close,
|
||||
}
|
||||
public Task DisplayAlert (String message, AlertMode alertMode = AlertMode.OK)
|
||||
{
|
||||
String title = StringUtil.OnEmpty(Title, MessageTitleDefault);
|
||||
String cancel = "OK";
|
||||
if (alertMode == AlertMode.Close)
|
||||
cancel = "Close";
|
||||
return DisplayAlert(title, message, cancel);
|
||||
}
|
||||
public enum ConfirmMode
|
||||
{
|
||||
YesNo,
|
||||
OkCancel
|
||||
}
|
||||
public async Task<bool> DisplayConfirm (String message, ConfirmMode confirmMode = ConfirmMode.OkCancel)
|
||||
{
|
||||
String title = StringUtil.OnEmpty(Title, MessageTitleDefault);
|
||||
String accept = "Yes";
|
||||
String cancel = "No";
|
||||
if (confirmMode == ConfirmMode.OkCancel)
|
||||
{
|
||||
accept = "OK";
|
||||
cancel = "Cancel";
|
||||
}
|
||||
return await DisplayAlert(title, message, accept, cancel);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P a g e E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnParentSet ()
|
||||
{
|
||||
base.OnParentSet();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnPropertyChanged ([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
base.OnPropertyChanged(propertyName);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnAppearing ()
|
||||
{
|
||||
base.OnAppearing();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnDisappearing ()
|
||||
{
|
||||
base.OnDisappearing();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Panels
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxPanel : SaxContentView
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxPanel ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n f i g u r e C o m p o n e n t s
|
||||
//-------------------------------------------------------------------
|
||||
protected override void ConfigureComponents ()
|
||||
{
|
||||
base.ConfigureComponents();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l A c t i v i t y
|
||||
//-------------------------------------------------------------------
|
||||
protected override void SetControlActivity ()
|
||||
{
|
||||
}
|
||||
protected override void SetControlsReadOnly ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P a n e l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnParentSet ()
|
||||
{
|
||||
base.OnParentSet();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnPropertyChanging ([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
base.OnPropertyChanging(propertyName);
|
||||
}
|
||||
protected override void OnPropertyChanged ([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
base.OnPropertyChanged(propertyName);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnChildAdded (Element child)
|
||||
{
|
||||
base.OnChildAdded(child);
|
||||
}
|
||||
[Obsolete("OnChildRemoved(Element) is obsolete as of version 4.8.0. Please use OnChildRemoved(Element, int) instead.")]
|
||||
protected override void OnChildRemoved (Element child)
|
||||
{
|
||||
base.OnChildRemoved(child);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnSizeAllocated (double width, double height)
|
||||
{
|
||||
base.OnSizeAllocated(width, height);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Controls;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Layouts;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Panels
|
||||
{
|
||||
//=======================================================================
|
||||
public class SacsFilterPropertyType
|
||||
{
|
||||
public enum FilterMode { Text, DropDownList }
|
||||
public SacsFilterPropertyType (int propertyType, String caption)
|
||||
{
|
||||
PropertyType = propertyType;
|
||||
Caption = caption;
|
||||
}
|
||||
public int PropertyType { get; }
|
||||
public String Caption { get; }
|
||||
public FilterMode Mode { get; set; } = FilterMode.Text;
|
||||
}
|
||||
public class SaxPanel_ItemFilter : SaxWrapLayout
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public class Config
|
||||
{
|
||||
public List<SacsFilterPropertyType> FilterPropertyTypes { get; } = new List<SacsFilterPropertyType>();
|
||||
public ushort FiltersToDisplay { get; set; } = 2;
|
||||
public int PropertyTypeWidth { get; set; } = 100;
|
||||
public int PropertyValueWidth { get; set; } = 120;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private Config config;
|
||||
private SaxPanel_ItemFilterProperty[] itemFilterProperties = new SaxPanel_ItemFilterProperty[0];
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxPanel_ItemFilter (Config config)
|
||||
{
|
||||
this.config = config;
|
||||
InitialiseComponents();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public int FilterCount { get { return Math.Min(config.FiltersToDisplay, config.FilterPropertyTypes.Count); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Configure.
|
||||
public void SetConfig (Config config)
|
||||
{
|
||||
this.config = config;
|
||||
ConfigurePanel();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P u b l i c I n t e r f a c e
|
||||
//-------------------------------------------------------------------
|
||||
public String GetFilterPropertyValue (int propertyType)
|
||||
{
|
||||
foreach (SaxPanel_ItemFilterProperty propertyFilter in itemFilterProperties)
|
||||
{
|
||||
if (propertyFilter.SelectedPropertyType == propertyType)
|
||||
return propertyFilter.PropertyValue;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// I n i t i a l i s e
|
||||
//-------------------------------------------------------------------
|
||||
private void InitialiseComponents ()
|
||||
{
|
||||
// Styling.
|
||||
SpacingX = 8.0;
|
||||
SpacingY = 4.0;
|
||||
BackgroundColor = Color.Transparent;
|
||||
|
||||
ConfigurePanel();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n f i g u r e P a n e l
|
||||
//-------------------------------------------------------------------
|
||||
private void ConfigurePanel ()
|
||||
{
|
||||
// Clear filter panels.
|
||||
Children.Clear();
|
||||
|
||||
// Reconfigure fiter properties.
|
||||
if (itemFilterProperties.Length != FilterCount)
|
||||
{
|
||||
// Create new set of filters and copy previous filters across up to required number.
|
||||
SaxPanel_ItemFilterProperty [] itemFilterPropertiesNew = new SaxPanel_ItemFilterProperty[FilterCount];
|
||||
for (int filterIdx = 0; filterIdx < Math.Min(itemFilterProperties.Length, FilterCount); filterIdx++)
|
||||
itemFilterPropertiesNew[filterIdx] = itemFilterProperties[filterIdx];
|
||||
for (int filterIdx = itemFilterProperties.Length; filterIdx < FilterCount; filterIdx++)
|
||||
{
|
||||
itemFilterPropertiesNew[filterIdx] = new SaxPanel_ItemFilterProperty(new SaxPanel_ItemFilterProperty.Config());
|
||||
itemFilterPropertiesNew[filterIdx].PropertyFilterChanged += SaxPanel_ItemFilter_PropertyFilterChanged;
|
||||
}
|
||||
itemFilterProperties = itemFilterPropertiesNew;
|
||||
}
|
||||
|
||||
// Retrieve currently selected property types.
|
||||
List<int> selectedPropertyTypes = new List<int>();
|
||||
for (int filterIdx = 0; filterIdx < FilterCount; filterIdx++)
|
||||
{
|
||||
int selectedPropertyType = itemFilterProperties[filterIdx].SelectedPropertyType;
|
||||
if (selectedPropertyType >= 0 && !selectedPropertyTypes.Contains(selectedPropertyType))
|
||||
selectedPropertyTypes.Add(selectedPropertyType);
|
||||
}
|
||||
|
||||
// Configure filter panels.
|
||||
for (int filterIdx = 0; filterIdx < FilterCount; filterIdx++)
|
||||
{
|
||||
SaxPanel_ItemFilterProperty propertyPanel = itemFilterProperties[filterIdx];
|
||||
|
||||
// Determine the property types to display - remove property types selected in other panels.
|
||||
List<SacsFilterPropertyType> filterPropertyTypes = new List<SacsFilterPropertyType>(config.FilterPropertyTypes);
|
||||
filterPropertyTypes.RemoveAll(item => item.PropertyType != propertyPanel.SelectedPropertyType && selectedPropertyTypes.Contains(item.PropertyType));
|
||||
if (filterPropertyTypes.Count == 0) continue;
|
||||
|
||||
SaxPanel_ItemFilterProperty.Config propertyPanelConfig = new SaxPanel_ItemFilterProperty.Config();
|
||||
propertyPanelConfig.FilterPropertyTypes.AddRange(filterPropertyTypes);
|
||||
propertyPanelConfig.PropertyTypeWidth = config.PropertyTypeWidth;
|
||||
propertyPanelConfig.PropertyValueWidth = config.PropertyValueWidth;
|
||||
propertyPanel.SetConfig(propertyPanelConfig);
|
||||
|
||||
// Include the selecetd type in the list of not already present.
|
||||
int selectedPropertyType = propertyPanel.SelectedPropertyType;
|
||||
if (selectedPropertyType >= 0 && !selectedPropertyTypes.Contains(selectedPropertyType))
|
||||
selectedPropertyTypes.Add(selectedPropertyType);
|
||||
|
||||
// Add panel to the layout.
|
||||
Children.Add(propertyPanel);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// F i l t e r E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
public class FilterChangedEventArgs : EventArgs
|
||||
{
|
||||
public int PropertyType { get; set; } = -1;
|
||||
}
|
||||
public event EventHandler<FilterChangedEventArgs> FilterChanged;
|
||||
private void FireFilterChangedEvent (int propertyType)
|
||||
{
|
||||
FilterChangedEventArgs filterChangedEventArgs = new FilterChangedEventArgs()
|
||||
{
|
||||
PropertyType = propertyType,
|
||||
};
|
||||
if (FilterChanged != null) FilterChanged.Invoke(this, filterChangedEventArgs);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
private void SaxPanel_ItemFilter_PropertyFilterChanged (object sender, SaxPanel_ItemFilterProperty.PropertyFilterChangedEventArgs e)
|
||||
{
|
||||
FireFilterChangedEvent(e.PropertyType);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Layouts;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Panels
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxPanel_ItemFilterProperty : SaxPanel
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public class Config
|
||||
{
|
||||
public List<SacsFilterPropertyType> FilterPropertyTypes { get; } = new List<SacsFilterPropertyType>();
|
||||
public GridLength Height { get; set; } = GridLength.Auto;
|
||||
public int PropertyTypeWidth { get; set; } = 0;
|
||||
public int PropertyValueWidth { get; set; } = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private Config config;
|
||||
private SaxGrid grid;
|
||||
private SaxPicker pickerPropertyType = new SaxPicker();
|
||||
private SaxEntry entryPropertyValue = new SaxEntry() { Text = "", HorizontalOptions = LayoutOptions.FillAndExpand };
|
||||
private SaxPicker pickerPropertyValue = new SaxPicker(){ HorizontalOptions = LayoutOptions.FillAndExpand , IsVisible = false };
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxPanel_ItemFilterProperty (Config config)
|
||||
{
|
||||
this.config = config;
|
||||
InitialiseComponents();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public bool Initialising { get; set; } = true;
|
||||
private SacsFilterPropertyType SelectedProperty { get { return config.FilterPropertyTypes.Find(item => item.PropertyType == StringUtil.ToInt(pickerPropertyType.SelectedItemCode)); } }
|
||||
public int SelectedPropertyType { get { return SelectedProperty?.PropertyType ?? -1; } }
|
||||
public String PropertyValue
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SelectedProperty.Mode == SacsFilterPropertyType.FilterMode.DropDownList)
|
||||
return pickerPropertyValue.SelectedItemCode;
|
||||
return entryPropertyValue.Text;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Configure.
|
||||
public void SetConfig (Config config)
|
||||
{
|
||||
this.config = config;
|
||||
ConfigurePanel();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// I n i t i a l i s e
|
||||
//-------------------------------------------------------------------
|
||||
private void InitialiseComponents ()
|
||||
{
|
||||
// Grid - property type picker followed by property value control.
|
||||
grid = new SaxGrid()
|
||||
{
|
||||
BackgroundColor = Color.Transparent,
|
||||
RowSpacing = 0,
|
||||
ColumnSpacing = 4,
|
||||
RowDefinitions = new RowDefinitionCollection()
|
||||
{
|
||||
// Single row.
|
||||
new RowDefinition(){ Height = config.Height }
|
||||
},
|
||||
ColumnDefinitions = new ColumnDefinitionCollection()
|
||||
{
|
||||
// Two columns - property type & value.
|
||||
new ColumnDefinition(){ Width = config.PropertyTypeWidth > 0 ? config.PropertyTypeWidth : GridLength.Auto },
|
||||
new ColumnDefinition(){ Width = config.PropertyValueWidth > 0 ? config.PropertyValueWidth : GridLength.Auto }
|
||||
}
|
||||
};
|
||||
Content = grid;
|
||||
|
||||
// Property type.
|
||||
if (config.PropertyTypeWidth > 0)
|
||||
pickerPropertyType.WidthRequest = config.PropertyTypeWidth;
|
||||
grid.Children.Add(pickerPropertyType, 0, 0);
|
||||
pickerPropertyType.SelectedIndexChanged += PickerPropertyType_SelectedIndexChanged;
|
||||
|
||||
// Property value.
|
||||
if (config.PropertyValueWidth > 0)
|
||||
entryPropertyValue.WidthRequest = config.PropertyValueWidth;
|
||||
entryPropertyValue.TextChanged += EntryPropertyValue_TextChanged;
|
||||
grid.Children.Add(entryPropertyValue, 1, 0);
|
||||
if (config.PropertyValueWidth > 0)
|
||||
pickerPropertyValue.WidthRequest = config.PropertyValueWidth;
|
||||
pickerPropertyValue.SelectedIndexChanged += PickerPropertyValue_SelectedIndexChanged;
|
||||
grid.Children.Add(pickerPropertyValue, 1, 0);
|
||||
|
||||
ConfigurePanel();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n f i g u r e P a n e l
|
||||
//-------------------------------------------------------------------
|
||||
private void ConfigurePanel ()
|
||||
{
|
||||
Initialising = true;
|
||||
|
||||
// Configure layout.
|
||||
grid.ColumnDefinitions.Clear();
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = config.PropertyTypeWidth });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = config.PropertyValueWidth });
|
||||
|
||||
// Make a note of the currently selected property type.
|
||||
int selectedPropertyType = SelectedPropertyType;
|
||||
pickerPropertyType.ClearItems();
|
||||
|
||||
// Populate list of property types.
|
||||
foreach (SacsFilterPropertyType propertyType in config.FilterPropertyTypes)
|
||||
{
|
||||
pickerPropertyType.AddItem(propertyType.PropertyType.ToString(), propertyType.Caption);
|
||||
}
|
||||
pickerPropertyType.SelectedItemCode = selectedPropertyType.ToString();
|
||||
if (pickerPropertyType.SelectedIndex < 0 && pickerPropertyType.Items.Count > 0)
|
||||
pickerPropertyType.SelectedIndex = 0;
|
||||
|
||||
Initialising = false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P r o p e r t y F i l t e r E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
public class PropertyFilterChangedEventArgs : EventArgs
|
||||
{
|
||||
public int PropertyType { get; set; } = -1;
|
||||
}
|
||||
public event EventHandler<PropertyFilterChangedEventArgs> PropertyFilterChanged;
|
||||
private void FireFilterChangedEvent (int propertyType)
|
||||
{
|
||||
if (Initialising) return;
|
||||
PropertyFilterChangedEventArgs filterChangedEventArgs = new PropertyFilterChangedEventArgs()
|
||||
{
|
||||
PropertyType = propertyType,
|
||||
};
|
||||
if (PropertyFilterChanged != null) PropertyFilterChanged.Invoke(this, filterChangedEventArgs);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private void PickerPropertyType_SelectedIndexChanged (object sender, EventArgs e)
|
||||
{
|
||||
FireFilterChangedEvent(SelectedPropertyType);
|
||||
}
|
||||
private void EntryPropertyValue_TextChanged (object sender, TextChangedEventArgs e)
|
||||
{
|
||||
FireFilterChangedEvent(SelectedPropertyType);
|
||||
}
|
||||
private void PickerPropertyValue_SelectedIndexChanged (object sender, EventArgs e)
|
||||
{
|
||||
FireFilterChangedEvent(SelectedPropertyType);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Controls;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Layouts;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Views;
|
||||
using Sarand.Net.Mobile.Xamarin.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Panels
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxPanel_ItemListHeader : SaxPanel
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public class Config
|
||||
{
|
||||
public Thickness? Margin { get; set; } = new Thickness(0, 0, 0, 8);
|
||||
public String Caption { get; set; }
|
||||
public double HeaderBorderWidth { get; set; } = 4.0;
|
||||
public float HeaderBorderRadius { get; set; } = 8.0f;
|
||||
public Color HeaderBorderColor { get; set; } = Color.FromHex("#808080");
|
||||
public Color HeaderBackgroundColor { get; set; } = Color.FromHex("#F0F0F0");
|
||||
// Labels.
|
||||
// Styling.
|
||||
public double CaptionLabelFontSizeRatio { get; set; } = 1.0;
|
||||
public double PagingLabelFontSizeRatio { get; set; } = 1.0;
|
||||
public Thickness? LabelMargin { get; set; } = null;
|
||||
// Paging controls.
|
||||
public static int PagingButtonWidthMin { get; } = 40;
|
||||
public static int PagingButtonWidthMax { get; } = 64;
|
||||
public static int PagingButtonWidthDefault { get; } = PagingButtonWidthMin;
|
||||
public int PagingButtonWidth { get; set; } = PagingButtonWidthDefault;
|
||||
public static int PagingButtonHeightMin { get; } = 40;
|
||||
public static int PagingButtonHeightMax { get; } = 64;
|
||||
public static int PagingButtonHeightDefault { get; } = PagingButtonHeightMin;
|
||||
public int PagingButtonHeight { get; set; } = PagingButtonHeightDefault;
|
||||
// Filters.
|
||||
public List<SacsFilterPropertyType> FilterPropertyTypes { get; } = new List<SacsFilterPropertyType>();
|
||||
public ushort FiltersToDisplay { get; set; } = 2;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private Config config;
|
||||
// Layout.
|
||||
private SaxFrame frame = new SaxFrame();
|
||||
private SaxStackLayout mainLayout = new SaxStackLayout() { Orientation = StackOrientation.Vertical };
|
||||
// Header.
|
||||
private SaxWrapLayout headerLayout = new SaxWrapLayout() { SpacingX = 8.0 };
|
||||
private SaxContentView captionLabelView = new SaxContentView();
|
||||
private SaxLabel labelCaption = new SaxLabel() { Text = "" };
|
||||
private double initialLabelFontSize = 0;
|
||||
// Paging.
|
||||
private class PagingData : DbQuery.Paging
|
||||
{
|
||||
public int TotalItems { get; set; }
|
||||
public int TotalPages { get { return PageLength > 0 ? (int)Math.Ceiling((double)TotalItems / PageLength) : 0; } }
|
||||
public override bool Paged { get { return base.Paged && TotalItems > 0; } }
|
||||
}
|
||||
private readonly PagingData paging = new PagingData();
|
||||
private SaxStackLayout pagingStack = new SaxStackLayout() { Orientation = StackOrientation.Horizontal };
|
||||
private SaxLabel labelPaging = new SaxLabel() { Text = "[Paging]" };
|
||||
private SaxImageButton buttonPagingFirst = new SaxImageButton() { WidthRequest = 32, HeightRequest = 32, Aspect = Aspect.AspectFit, Padding = new Thickness(2, 4), BackgroundColor = Color.Transparent };
|
||||
private SaxImageButton buttonPagingPrev = new SaxImageButton() { WidthRequest = 32, HeightRequest = 32, Aspect = Aspect.AspectFit, Padding = new Thickness(2, 4), BackgroundColor = Color.Transparent };
|
||||
private SaxImageButton buttonPagingNext = new SaxImageButton() { WidthRequest = 32, HeightRequest = 32, Aspect = Aspect.AspectFit, Padding = new Thickness(2, 4), BackgroundColor = Color.Transparent };
|
||||
private SaxImageButton buttonPagingLast = new SaxImageButton() { WidthRequest = 32, HeightRequest = 32, Aspect = Aspect.AspectFit, Padding = new Thickness(2, 4), BackgroundColor = Color.Transparent };
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxPanel_ItemListHeader(Config config)
|
||||
{
|
||||
this.config = config;
|
||||
initialLabelFontSize = labelCaption.FontSize;
|
||||
InitialiseComponents();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
// Filter.
|
||||
public SaxPanel_ItemFilter PanelFilter { get; private set; }
|
||||
// Paging.
|
||||
public uint PageNo { get { return paging.PageNo; } }
|
||||
public ushort PageLength { get { return paging.PageLength; } }
|
||||
public int TotalItems { get { return paging.TotalItems; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// I n i t i a l i s e
|
||||
//-------------------------------------------------------------------
|
||||
private void InitialiseComponents()
|
||||
{
|
||||
// Frame - to allow rounded corners.
|
||||
Content = frame;
|
||||
frame.Content = mainLayout;
|
||||
|
||||
// Header.
|
||||
mainLayout.Spacing = 0;
|
||||
mainLayout.HorizontalOptions = LayoutOptions.StartAndExpand;
|
||||
mainLayout.BackgroundColor = Color.Transparent;
|
||||
//headerLayout.BackgroundColor = Color.LightYellow;
|
||||
mainLayout.Children.Add(headerLayout);
|
||||
|
||||
// Header - Caption.
|
||||
captionLabelView.VerticalOptions = LayoutOptions.Center;
|
||||
labelCaption.FontAttributes = FontAttributes.Bold;
|
||||
labelCaption.HorizontalOptions = LayoutOptions.StartAndExpand;
|
||||
labelCaption.VerticalOptions = LayoutOptions.CenterAndExpand;
|
||||
labelCaption.LineBreakMode = LineBreakMode.NoWrap;
|
||||
labelCaption.PropertyChanging += LabelCaption_PropertyChanging;
|
||||
// Label is embedded in view to ensure correct sizing.
|
||||
captionLabelView.Content = labelCaption;
|
||||
headerLayout.Children.Add(captionLabelView);
|
||||
|
||||
// Header - Paging.
|
||||
pagingStack.HorizontalOptions = LayoutOptions.EndAndExpand;
|
||||
pagingStack.VerticalOptions = LayoutOptions.CenterAndExpand;
|
||||
headerLayout.Children.Add(pagingStack);
|
||||
labelPaging.VerticalOptions = LayoutOptions.CenterAndExpand;
|
||||
pagingStack.Children.Add(labelPaging);
|
||||
pagingStack.Children.Add(buttonPagingFirst);
|
||||
pagingStack.Children.Add(buttonPagingPrev);
|
||||
pagingStack.Children.Add(buttonPagingNext);
|
||||
pagingStack.Children.Add(buttonPagingLast);
|
||||
|
||||
// Paging actions.
|
||||
buttonPagingFirst.Clicked += ButtonPagingFirst_Clicked;
|
||||
buttonPagingPrev.Clicked += ButtonPagingPrev_Clicked;
|
||||
buttonPagingNext.Clicked += ButtonPagingNext_Clicked;
|
||||
buttonPagingLast.Clicked += ButtonPagingLast_Clicked;
|
||||
|
||||
// Complete panel configuration.
|
||||
ConfigurePanel();
|
||||
}
|
||||
|
||||
private void LabelCaption_PropertyChanging(object sender, PropertyChangingEventArgs e)
|
||||
{
|
||||
if (e.PropertyName.EqualsCI("Height"))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n f i g u r e P a n e l
|
||||
//-------------------------------------------------------------------
|
||||
private void ConfigurePanel()
|
||||
{
|
||||
if (config.Margin != null)
|
||||
frame.Margin = (Thickness)config.Margin;
|
||||
|
||||
// Header.
|
||||
labelCaption.Text = StringUtil.EmptyOnNull(config.Caption);
|
||||
frame.Padding = new Thickness(config.HeaderBorderWidth);
|
||||
frame.CornerRadius = config.HeaderBorderRadius;
|
||||
frame.BorderColor = config.HeaderBorderColor;
|
||||
frame.BackgroundColor = config.HeaderBackgroundColor;
|
||||
|
||||
// Labels.
|
||||
labelCaption.FontSize = initialLabelFontSize * config.CaptionLabelFontSizeRatio;
|
||||
labelPaging.FontSize = initialLabelFontSize * config.PagingLabelFontSizeRatio;
|
||||
if (config.LabelMargin != null)
|
||||
{
|
||||
labelCaption.Margin = (Thickness)config.LabelMargin;
|
||||
labelPaging.Margin = (Thickness)config.LabelMargin;
|
||||
}
|
||||
|
||||
// Paging controls.
|
||||
buttonPagingFirst.Source = SacsImageUtils.GetImageFromByteArray(SacsResourceHelper.GetResourceImage(SacsResourceHelper.ImageResource.Arrow_Left_Double_Black_24_png));
|
||||
buttonPagingFirst.WidthRequest = Math.Max(Config.PagingButtonWidthMin, Math.Min(Config.PagingButtonWidthMax, config.PagingButtonWidth));
|
||||
buttonPagingFirst.HeightRequest = Math.Max(Config.PagingButtonHeightMin, Math.Min(Config.PagingButtonHeightMax, config.PagingButtonHeight));
|
||||
buttonPagingPrev.Source = SacsImageUtils.GetImageFromByteArray(SacsResourceHelper.GetResourceImage(SacsResourceHelper.ImageResource.Arrow_Left_Black_24_png));
|
||||
buttonPagingPrev.WidthRequest = Math.Max(Config.PagingButtonWidthMin, Math.Min(Config.PagingButtonWidthMax, config.PagingButtonWidth));
|
||||
buttonPagingPrev.HeightRequest = Math.Max(Config.PagingButtonHeightMin, Math.Min(Config.PagingButtonHeightMax, config.PagingButtonHeight));
|
||||
buttonPagingNext.Source = SacsImageUtils.GetImageFromByteArray(SacsResourceHelper.GetResourceImage(SacsResourceHelper.ImageResource.Arrow_Right_Black_24_png));
|
||||
buttonPagingNext.WidthRequest = Math.Max(Config.PagingButtonWidthMin, Math.Min(Config.PagingButtonWidthMax, config.PagingButtonWidth));
|
||||
buttonPagingNext.HeightRequest = Math.Max(Config.PagingButtonHeightMin, Math.Min(Config.PagingButtonHeightMax, config.PagingButtonHeight));
|
||||
buttonPagingLast.Source = SacsImageUtils.GetImageFromByteArray(SacsResourceHelper.GetResourceImage(SacsResourceHelper.ImageResource.Arrow_Right_Double_Black_24_png));
|
||||
buttonPagingLast.WidthRequest = Math.Max(Config.PagingButtonWidthMin, Math.Min(Config.PagingButtonWidthMax, config.PagingButtonWidth));
|
||||
buttonPagingLast.HeightRequest = Math.Max(Config.PagingButtonHeightMin, Math.Min(Config.PagingButtonHeightMax, config.PagingButtonHeight));
|
||||
RefreshPaging();
|
||||
|
||||
// Property type filters.
|
||||
SaxPanel_ItemFilter.Config propertyFilterConfig = new SaxPanel_ItemFilter.Config();
|
||||
propertyFilterConfig.FilterPropertyTypes.AddRange(config.FilterPropertyTypes);
|
||||
propertyFilterConfig.FiltersToDisplay = config.FiltersToDisplay;
|
||||
if (PanelFilter == null)
|
||||
{
|
||||
PanelFilter = new SaxPanel_ItemFilter(propertyFilterConfig);
|
||||
mainLayout.Children.Add(PanelFilter);
|
||||
}
|
||||
else
|
||||
{
|
||||
PanelFilter.SetConfig(propertyFilterConfig);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P a g i n g
|
||||
//-------------------------------------------------------------------
|
||||
public void SetPaging(uint pageNo, ushort pageLength, int totalItems)
|
||||
{
|
||||
paging.PageNo = pageNo;
|
||||
paging.PageLength = pageLength;
|
||||
paging.TotalItems = totalItems;
|
||||
RefreshPaging();
|
||||
}
|
||||
private void RefreshPaging()
|
||||
{
|
||||
String pagingText = "";
|
||||
Boolean paged = (paging.Paged && paging.TotalPages > 1);
|
||||
if (paging.TotalItems > 0)
|
||||
{
|
||||
if (paged)
|
||||
pagingText = "Page " + paging.PageNo + " of " + paging.TotalPages;
|
||||
else
|
||||
pagingText = paging.TotalItems + " items";
|
||||
}
|
||||
labelPaging.Text = pagingText;
|
||||
// Control visibility.
|
||||
labelPaging.IsVisible = !StringUtil.IsEmpty(labelPaging.Text);
|
||||
buttonPagingFirst.IsVisible = paged;
|
||||
buttonPagingPrev.IsVisible = paged;
|
||||
buttonPagingNext.IsVisible = paged;
|
||||
buttonPagingLast.IsVisible = paged;
|
||||
// Button activity.
|
||||
buttonPagingFirst.IsEnabled = paging.PageNo > 1;
|
||||
buttonPagingPrev.IsEnabled = paging.PageNo > 1;
|
||||
buttonPagingNext.IsEnabled = paging.PageNo < paging.TotalPages;
|
||||
buttonPagingLast.IsEnabled = paging.PageNo < paging.TotalPages;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Paging events.
|
||||
public enum PagingActionType
|
||||
{
|
||||
Unknown,
|
||||
First,
|
||||
Next,
|
||||
Prev,
|
||||
Last
|
||||
}
|
||||
public class PagingActionEventArgs : EventArgs
|
||||
{
|
||||
public PagingActionType PagingActionType { get; set; } = PagingActionType.Unknown;
|
||||
}
|
||||
public event EventHandler<PagingActionEventArgs> PagingAction;
|
||||
private void FirePagingActionEvent(PagingActionType pagingActionType)
|
||||
{
|
||||
PagingActionEventArgs filterChangedEventArgs = new PagingActionEventArgs()
|
||||
{
|
||||
PagingActionType = pagingActionType,
|
||||
};
|
||||
if (PagingAction != null) PagingAction.Invoke(this, filterChangedEventArgs);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Paging actions.
|
||||
private void ButtonPagingFirst_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
FirePagingActionEvent(PagingActionType.First);
|
||||
}
|
||||
private void ButtonPagingPrev_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
FirePagingActionEvent(PagingActionType.Prev);
|
||||
}
|
||||
private void ButtonPagingNext_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
FirePagingActionEvent(PagingActionType.Next);
|
||||
}
|
||||
private void ButtonPagingLast_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
FirePagingActionEvent(PagingActionType.Last);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P a n e l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Controls;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Layouts;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Views;
|
||||
using Sarand.Net.Mobile.Xamarin.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Panels
|
||||
{
|
||||
//=======================================================================
|
||||
/// <summary>
|
||||
/// Panel to display with item list where no filter required, eg. items associated with parent.
|
||||
/// <para>- Message shown to left</para>
|
||||
/// <para>- Buttons shown to right</para>
|
||||
/// </summary>
|
||||
public class SaxPanel_ItemListSummary : SaxContentView
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private SacsMessage message;
|
||||
private bool showAddButton = false;
|
||||
private double actionButtonSpacing = 4.0;
|
||||
// Panel layout.
|
||||
private SaxStackLayout panelLayout = new SaxStackLayout() { Orientation = StackOrientation.Horizontal };
|
||||
private SaxContentView panelMessage = new SaxContentView();
|
||||
private SaxLabel labelMessage = new SaxLabel() { HorizontalOptions = LayoutOptions.Start};
|
||||
// Action butons.
|
||||
private SaxStackLayout panelActions = new SaxStackLayout() { Orientation = StackOrientation.Horizontal };
|
||||
private SaxImageButton buttonAddItem = new SaxImageButton() { IsVisible = false, HorizontalOptions = LayoutOptions.End, VerticalOptions = LayoutOptions.Start };
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxPanel_ItemListSummary ()
|
||||
{
|
||||
// Panel layout.
|
||||
panelLayout.HorizontalOptions = LayoutOptions.Fill;
|
||||
Content = panelLayout;
|
||||
|
||||
// Message.
|
||||
panelMessage.HorizontalOptions = LayoutOptions.Fill;
|
||||
panelMessage.VerticalOptions = LayoutOptions.Fill;
|
||||
//panelMessage.BackgroundColor = Color.LightGoldenrodYellow;
|
||||
panelLayout.Children.Add(panelMessage);
|
||||
labelMessage.HorizontalOptions = LayoutOptions.Center;
|
||||
labelMessage.VerticalOptions = LayoutOptions.Center;
|
||||
panelMessage.Content = labelMessage;
|
||||
|
||||
// Action buttons.
|
||||
panelActions.HorizontalOptions = LayoutOptions.EndAndExpand;
|
||||
panelLayout.Children.Add(panelActions);
|
||||
|
||||
// 'Add' button.
|
||||
buttonAddItem.IsVisible = showAddButton;
|
||||
buttonAddItem.Padding = new Thickness(0, 0, actionButtonSpacing, 0);
|
||||
buttonAddItem.BackgroundColor = Color.Transparent;
|
||||
buttonAddItem.Source = SacsImageUtils.GetImageFromByteArray(SacsResourceHelper.GetResourceImage(SacsResourceHelper.ImageResource.IconShock_Add_Green_72_png));
|
||||
buttonAddItem.Clicked += ButtonAddItem_Clicked;
|
||||
panelActions.Children.Add(buttonAddItem);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
// Message.
|
||||
public double DefaultMessageFontSize { get { return labelMessage.DefaultFontSize; } }
|
||||
public double MessageFontSize
|
||||
{
|
||||
get { return labelMessage.FontSize; }
|
||||
set { labelMessage.FontSize = value; }
|
||||
}
|
||||
// Action buttons.
|
||||
public double ActionButtonSpacing
|
||||
{
|
||||
get { return actionButtonSpacing; }
|
||||
set
|
||||
{
|
||||
if (actionButtonSpacing == value) return;
|
||||
buttonAddItem.Padding = new Thickness(0, 0, actionButtonSpacing, 0);
|
||||
}
|
||||
}
|
||||
public bool ShowAddButton
|
||||
{
|
||||
get { return showAddButton; }
|
||||
set { if (showAddButton == value) return; showAddButton = value; buttonAddItem.IsVisible = showAddButton; }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// M e s s a g e
|
||||
//-------------------------------------------------------------------
|
||||
public void ClearMessage ()
|
||||
{
|
||||
message = null;
|
||||
labelMessage.Text = "";
|
||||
}
|
||||
public void SetMessage (String message, SaMessageLevel messageLevel = SaMessageLevel.Info)
|
||||
{
|
||||
SetMessage(new SacsMessage(message, messageLevel));
|
||||
}
|
||||
public void SetMessage (SacsMessage message)
|
||||
{
|
||||
this.message = message;
|
||||
labelMessage.Text = (message != null ? message.Message : "");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// A c t i o n B u t t o n s
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P a n e l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
public event EventHandler<EventArgs> AddClicked;
|
||||
protected virtual void ButtonAddItem_Clicked (object sender, EventArgs e)
|
||||
{
|
||||
if (AddClicked != null) AddClicked.Invoke(sender, e);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Controls;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Layouts;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Panels
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxPanel_Messages : SaxPanel
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public class Config
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private Config config;
|
||||
private readonly List<SacsMessage> messages = new List<SacsMessage>();
|
||||
// Components.
|
||||
private SaxStackLayout mainLayout = new SaxStackLayout() { Orientation = StackOrientation.Vertical };
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxPanel_Messages (Config config)
|
||||
{
|
||||
this.config = config;
|
||||
Content = mainLayout;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// M e s s a g e s
|
||||
//-------------------------------------------------------------------
|
||||
public void ClearMessages ()
|
||||
{
|
||||
messages.Clear();
|
||||
RefreshLayout();
|
||||
}
|
||||
public void AddMessage (SacsMessage message)
|
||||
{
|
||||
messages.Add(message);
|
||||
RefreshLayout();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// R e f r e s h L a y o u t
|
||||
//-------------------------------------------------------------------
|
||||
private void RefreshLayout()
|
||||
{
|
||||
// Reset layout.
|
||||
IsVisible = messages.Count > 0;
|
||||
mainLayout.Children.Clear();
|
||||
|
||||
foreach (SacsMessage message in messages)
|
||||
{
|
||||
SaxPanel messagePanel = new SaxPanel();
|
||||
messagePanel.Content = new SaxLabel() { Text = message.Message };
|
||||
mainLayout.Children.Add(messagePanel);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P a n e l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Controls;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Layouts;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Panels
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxPanel_Progress : SaxContentView
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public class Config
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private Config config;
|
||||
// Panel layout.
|
||||
private SaxGrid gridPanel = new SaxGrid();
|
||||
private SaxContentView viewPanel = new SaxContentView();
|
||||
private SaxLabel labelProgressMessage = new SaxLabel();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxPanel_Progress (Config config)
|
||||
{
|
||||
this.config = config;
|
||||
InitialiseComponents();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public double ProgressMessageDefaultFontSize { get { return labelProgressMessage.DefaultFontSize; } }
|
||||
public double ProgressMessageFontSize { get { return labelProgressMessage.FontSize; } set { labelProgressMessage.FontSize = value; } }
|
||||
public FontAttributes ProgressMessageFontAttributes { get { return labelProgressMessage.FontAttributes; } set { labelProgressMessage.FontAttributes = value; } }
|
||||
public Color ProgressMessageColor { get { return labelProgressMessage.TextColor; } set { labelProgressMessage.TextColor = value; } }
|
||||
public String ProgressMessage { get { return labelProgressMessage.Text; } set { labelProgressMessage.Text = value; } }
|
||||
public Thickness ProgressMessagePadding { get { return viewPanel.Padding; } set { viewPanel.Padding = value; } }
|
||||
public Color ProgressMessageBackgroundColor { get { return viewPanel.BackgroundColor; } set { viewPanel.BackgroundColor = value; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// I n i t i a l i s e
|
||||
//-------------------------------------------------------------------
|
||||
private void InitialiseComponents ()
|
||||
{
|
||||
// Layout is a 3x3 grid with only the central cell populated.
|
||||
// All other cells are transparent/opaque.
|
||||
gridPanel.BackgroundColor = new Color(0, 0, 0, 0.5);
|
||||
gridPanel.HorizontalOptions = LayoutOptions.FillAndExpand;
|
||||
gridPanel.VerticalOptions = LayoutOptions.FillAndExpand;
|
||||
gridPanel.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
|
||||
gridPanel.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
|
||||
gridPanel.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
|
||||
gridPanel.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Star });
|
||||
gridPanel.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
|
||||
gridPanel.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Star });
|
||||
Content = gridPanel;
|
||||
|
||||
// The panel's view.
|
||||
viewPanel.Padding = new Thickness(12.0);
|
||||
viewPanel.BackgroundColor = Color.WhiteSmoke;
|
||||
viewPanel.HorizontalOptions = LayoutOptions.Center;
|
||||
viewPanel.VerticalOptions = LayoutOptions.Center;
|
||||
gridPanel.Children.Add(viewPanel, 1, 1);
|
||||
|
||||
// Progress message.
|
||||
viewPanel.Content = labelProgressMessage;
|
||||
|
||||
// Complete panel configuration.
|
||||
ConfigurePanel();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n f i g u r e P a n e l
|
||||
//-------------------------------------------------------------------
|
||||
private void ConfigurePanel ()
|
||||
{
|
||||
// Panel initialisation that depends on the configuration.
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P a n e l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Controls;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Layouts;
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Panels
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxPanel_PropertySummary : SaxContentView
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
private class PropertyData
|
||||
{
|
||||
public String Caption { get; set; }
|
||||
public String Value { get; set; }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private float internalFrameRadiusFactor = 0.8f;
|
||||
private readonly List<PropertyData> properties = new List<PropertyData>();
|
||||
// Panel components.
|
||||
private SaxFrame framePanel = new SaxFrame();
|
||||
private SaxFrame frameInternal = new SaxFrame();
|
||||
private SaxGrid gridProperties = new SaxGrid();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxPanel_PropertySummary ()
|
||||
{
|
||||
// View properties.
|
||||
//BackgroundColor = Color.Transparent;
|
||||
framePanel.CornerRadius = 8.0f;
|
||||
framePanel.Padding = new Thickness(2.0);
|
||||
framePanel.BackgroundColor = Color.Transparent;
|
||||
framePanel.BorderColor = framePanel.BorderColor;
|
||||
Content = framePanel;
|
||||
|
||||
// Frame.
|
||||
frameInternal.CornerRadius = framePanel.CornerRadius * internalFrameRadiusFactor;
|
||||
frameInternal.Padding = new Thickness(0);
|
||||
frameInternal.BorderColor = Color.White;
|
||||
frameInternal.BackgroundColor = Color.White;
|
||||
framePanel.Content = frameInternal;
|
||||
frameInternal.Content = gridProperties;
|
||||
|
||||
// Properties grid.
|
||||
gridProperties.Padding = new Thickness(4.0);
|
||||
gridProperties.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
|
||||
gridProperties.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
|
||||
|
||||
// Property styling.
|
||||
DefaultFontSize = new SaxLabel().FontSize;
|
||||
FontSize = DefaultFontSize;
|
||||
|
||||
ConfigureComponents();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public Color BorderColor
|
||||
{
|
||||
get { return framePanel.BorderColor; }
|
||||
set
|
||||
{
|
||||
framePanel.BorderColor = value;
|
||||
framePanel.BackgroundColor = value;
|
||||
}
|
||||
}
|
||||
public Thickness BorderWidth { get { return framePanel.Padding; } set { framePanel.Padding = value; } }
|
||||
public float CornerRadius
|
||||
{
|
||||
get { return framePanel.CornerRadius; }
|
||||
set
|
||||
{
|
||||
framePanel.CornerRadius = value;
|
||||
frameInternal.CornerRadius = framePanel.CornerRadius * internalFrameRadiusFactor;
|
||||
}
|
||||
}
|
||||
public Color PanelBackgroundColor
|
||||
{
|
||||
get { return frameInternal.BackgroundColor; }
|
||||
set
|
||||
{
|
||||
frameInternal.BorderColor = value;
|
||||
frameInternal.BackgroundColor = value;
|
||||
}
|
||||
}
|
||||
// Property label styling.
|
||||
public double DefaultFontSize { get; }
|
||||
public double FontSize { get; set; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// S u m m a r y P r o p e r t i e s
|
||||
//-------------------------------------------------------------------
|
||||
public void AddProperty (String caption, String value)
|
||||
{
|
||||
properties.Add(new PropertyData() { Caption = caption, Value = value });
|
||||
RefreshProperties();
|
||||
}
|
||||
public void ClearProperties ()
|
||||
{
|
||||
properties.Clear();
|
||||
RefreshProperties();
|
||||
}
|
||||
private void RefreshProperties ()
|
||||
{
|
||||
// Clear existing properties.
|
||||
gridProperties.Children.Clear();
|
||||
gridProperties.RowDefinitions.Clear();
|
||||
|
||||
foreach (PropertyData property in properties)
|
||||
{
|
||||
int rowIdx = gridProperties.RowDefinitions.Count;
|
||||
gridProperties.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
|
||||
gridProperties.Children.Add(new SaxLabel() { Text = property.Caption, FontSize = FontSize, HorizontalOptions = LayoutOptions.End }, 0, rowIdx);
|
||||
gridProperties.Children.Add(new SaxLabel() { Text = property.Value, FontSize = FontSize, HorizontalOptions = LayoutOptions.StartAndExpand, VerticalOptions = LayoutOptions.StartAndExpand }, 1, rowIdx);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n f i g u r e C o m p o n e n t s
|
||||
//-------------------------------------------------------------------
|
||||
protected override void ConfigureComponents ()
|
||||
{
|
||||
base.ConfigureComponents();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P a n e l E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Sarand.Net.Mobile.Xamarin.Forms.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Panels
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxTabPanel : SaxPanel
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxTabPanel (String caption, SaxContentView panel)
|
||||
{
|
||||
Caption = caption;
|
||||
|
||||
// This panel includes border layout around the actual tab panel content.
|
||||
Padding = new Thickness(2.0);
|
||||
BackgroundColor = Color.LightSlateGray;
|
||||
Content = panel;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public String Caption { get; }
|
||||
public Thickness BorderWidth
|
||||
{
|
||||
get { return Padding; }
|
||||
set { if (Padding == value) return; Padding = value; }
|
||||
}
|
||||
public Color BorderColor
|
||||
{
|
||||
get { return BackgroundColor; }
|
||||
set { if (BackgroundColor == value) return; BackgroundColor = value; }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// T a b P a n e l s
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Sarand.Net.Mobile.Xamarin.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Utils
|
||||
{
|
||||
//=======================================================================
|
||||
public static class SaxFormsUtil
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// D i s p l a y A l e r t a n d W a i t
|
||||
//-------------------------------------------------------------------
|
||||
public static void DisplayAlertSync (String title, String message, String cancel = "OK")
|
||||
{
|
||||
SaxThreadUtil.BeginInvokeOnMainThreadSync(async () => await Application.Current.MainPage.DisplayAlert(title, message, cancel));
|
||||
}
|
||||
public static bool DisplayConfirmSync (String title, String message, String accept = "Yes", String cancel = "No")
|
||||
{
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
Device.BeginInvokeOnMainThread(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
bool result = await Application.Current.MainPage.DisplayAlert(title, message, accept, cancel);
|
||||
tcs.SetResult(result);
|
||||
}
|
||||
catch (Exception ex) { tcs.SetException(ex); }
|
||||
});
|
||||
return tcs.Task.Result;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Utils
|
||||
{
|
||||
//=======================================================================
|
||||
public static class SaxPageUtil
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Views
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxBoxView : BoxView
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxBoxView ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Views
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxContentView : ContentView
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private bool readOnly = false;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxContentView ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public bool ReadOnly
|
||||
{
|
||||
get { return readOnly; }
|
||||
set { if (readOnly == value) return; readOnly = value; SetControlActivity(); }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n f i g u r e C o m p o n e n t s
|
||||
//-------------------------------------------------------------------
|
||||
protected virtual void ConfigureComponents ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o n t r o l A c t i v i t y
|
||||
//-------------------------------------------------------------------
|
||||
protected virtual void SetControlActivity ()
|
||||
{
|
||||
SetControlsReadOnly();
|
||||
}
|
||||
protected virtual void SetControlsReadOnly ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// V i e w E v e n t s
|
||||
//-------------------------------------------------------------------
|
||||
protected override void OnPropertyChanged ([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
base.OnPropertyChanged(propertyName);
|
||||
if (propertyName.EqualsCI(IsEnabledProperty.PropertyName))
|
||||
{
|
||||
SetControlActivity();
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Views
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxFrame : Frame
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxFrame ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Forms.Views
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaxView : View
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaxView ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Tasks
|
||||
{
|
||||
//=======================================================================
|
||||
public static class SaxThreadUtil
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// I n v o k e o n M a i n T h r e a d a n d W a i t
|
||||
//-------------------------------------------------------------------
|
||||
// Invoke task on main thread and wait for completion.
|
||||
public static void BeginInvokeOnMainThreadSync (Action taskFn)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<Object>();
|
||||
Device.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
taskFn();
|
||||
tcs.SetResult(null);
|
||||
}
|
||||
catch (Exception ex) { tcs.SetException(ex); }
|
||||
});
|
||||
}
|
||||
public static T BeginInvokeOnMainThreadSync<T> (Func<T> taskFn)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<T>();
|
||||
Device.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = taskFn();
|
||||
tcs.SetResult(result);
|
||||
}
|
||||
catch (Exception ex) { tcs.SetException(ex); }
|
||||
});
|
||||
return tcs.Task.Result;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Sarand.Net.Mobile.Xamarin.Utils
|
||||
{
|
||||
//=======================================================================
|
||||
public static class SacsImageUtils
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>
|
||||
/// Method that uses the ImageConverter object in .Net Framework to convert a byte array,
|
||||
/// presumably containing a JPEG or PNG file image, into an ImageSource.
|
||||
/// </summary>
|
||||
public static ImageSource GetImageFromByteArray (byte[] imageAsBytes)
|
||||
{
|
||||
return ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
Reference in New Issue
Block a user