2012-03-22 04:29:24 +04:00
|
|
|
|
//
|
2011-12-21 10:19:31 +04:00
|
|
|
|
// WidgetBackend.cs
|
2012-03-22 04:29:24 +04:00
|
|
|
|
//
|
|
|
|
|
// Authors:
|
2011-12-21 10:19:31 +04:00
|
|
|
|
// Carlos Alberto Cortez <calberto.cortez@gmail.com>
|
2012-03-22 04:29:24 +04:00
|
|
|
|
// Eric Maupin <ermau@xamarin.com>
|
|
|
|
|
//
|
2011-12-21 10:19:31 +04:00
|
|
|
|
// Copyright (c) 2011 Carlos Alberto Cortez
|
2012-03-22 04:29:24 +04:00
|
|
|
|
// Copyright (c) 2012 Xamarin, Inc.
|
|
|
|
|
//
|
2011-12-21 10:19:31 +04:00
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
// furnished to do so, subject to the following conditions:
|
2012-03-22 04:29:24 +04:00
|
|
|
|
//
|
2011-12-21 10:19:31 +04:00
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
|
// all copies or substantial portions of the Software.
|
2012-03-22 04:29:24 +04:00
|
|
|
|
//
|
2011-12-21 10:19:31 +04:00
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
// THE SOFTWARE.
|
|
|
|
|
|
|
|
|
|
using System;
|
2012-04-04 17:25:37 +04:00
|
|
|
|
using System.Collections.Specialized;
|
2012-03-28 17:55:46 +04:00
|
|
|
|
using System.Linq;
|
2011-12-21 10:19:31 +04:00
|
|
|
|
using System.Windows;
|
2011-12-28 23:46:21 +04:00
|
|
|
|
using System.Windows.Controls;
|
2012-04-24 01:56:34 +04:00
|
|
|
|
using System.Windows.Documents;
|
2012-03-10 00:46:39 +04:00
|
|
|
|
using System.Windows.Input;
|
2012-03-09 23:40:40 +04:00
|
|
|
|
using System.Windows.Media;
|
2011-12-28 23:46:21 +04:00
|
|
|
|
using SWM = System.Windows.Media;
|
2012-01-03 22:28:55 +04:00
|
|
|
|
using SWC = System.Windows.Controls; // When we need to resolve ambigituies.
|
2012-04-02 19:40:03 +04:00
|
|
|
|
using SW = System.Windows; // When we need to resolve ambigituies.
|
2011-12-21 10:19:31 +04:00
|
|
|
|
|
|
|
|
|
using Xwt.Backends;
|
2012-01-06 07:13:03 +04:00
|
|
|
|
using Xwt.Engine;
|
2012-03-09 23:40:40 +04:00
|
|
|
|
using Color = Xwt.Drawing.Color;
|
2011-12-21 10:19:31 +04:00
|
|
|
|
|
|
|
|
|
namespace Xwt.WPFBackend
|
|
|
|
|
{
|
2012-03-02 23:43:05 +04:00
|
|
|
|
public abstract class WidgetBackend
|
|
|
|
|
: Backend, IWidgetBackend, IWpfWidgetBackend
|
2011-12-21 10:19:31 +04:00
|
|
|
|
{
|
|
|
|
|
IWidgetEventSink eventSink;
|
2012-03-28 17:55:46 +04:00
|
|
|
|
WidgetEvent enabledEvents;
|
|
|
|
|
DragDropEffects currentDragEffect;
|
2012-03-29 04:02:59 +04:00
|
|
|
|
FrameworkElement widget;
|
2012-03-28 17:55:46 +04:00
|
|
|
|
|
2012-04-01 03:50:31 +04:00
|
|
|
|
class DragDropData
|
|
|
|
|
{
|
2012-04-04 17:25:37 +04:00
|
|
|
|
// Source
|
2012-04-01 03:50:31 +04:00
|
|
|
|
public bool AutodetectDrag;
|
|
|
|
|
public Rect DragRect;
|
2012-04-04 17:25:37 +04:00
|
|
|
|
// Target
|
|
|
|
|
public TransferDataType [] TargetTypes = new TransferDataType [0];
|
2012-04-01 03:50:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DragDropData dragDropInfo;
|
|
|
|
|
|
2012-03-28 17:55:46 +04:00
|
|
|
|
const WidgetEvent dragDropEvents = WidgetEvent.DragDropCheck | WidgetEvent.DragDrop | WidgetEvent.DragOver | WidgetEvent.DragOverCheck;
|
2011-12-21 10:19:31 +04:00
|
|
|
|
|
2012-03-29 04:02:59 +04:00
|
|
|
|
// Set to true when measuring a natural size for this widget
|
|
|
|
|
bool gettingNaturalSize;
|
|
|
|
|
|
|
|
|
|
// Set to true when calculating the default preferred size of the widget
|
|
|
|
|
bool calculatingPreferredSize;
|
|
|
|
|
|
2011-12-21 10:19:31 +04:00
|
|
|
|
void IWidgetBackend.Initialize (IWidgetEventSink eventSink)
|
|
|
|
|
{
|
|
|
|
|
this.eventSink = eventSink;
|
|
|
|
|
Initialize ();
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-02 23:43:05 +04:00
|
|
|
|
protected virtual void Initialize ()
|
2011-12-21 10:19:31 +04:00
|
|
|
|
{
|
|
|
|
|
}
|
2012-03-12 19:39:33 +04:00
|
|
|
|
|
|
|
|
|
~WidgetBackend ()
|
|
|
|
|
{
|
|
|
|
|
Dispose (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose ()
|
|
|
|
|
{
|
|
|
|
|
GC.SuppressFinalize (this);
|
|
|
|
|
Dispose (true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void Dispose (bool disposing)
|
2011-12-21 10:19:31 +04:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IWidgetEventSink EventSink {
|
|
|
|
|
get { return eventSink; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public object NativeWidget {
|
|
|
|
|
get { return Widget; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-29 04:02:59 +04:00
|
|
|
|
public FrameworkElement Widget {
|
|
|
|
|
get { return widget; }
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
widget = value;
|
|
|
|
|
if (widget is IWpfWidget)
|
|
|
|
|
((IWpfWidget)widget).Backend = this;
|
2012-03-29 22:44:52 +04:00
|
|
|
|
widget.InvalidateMeasure ();
|
2012-03-29 04:02:59 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-12-28 23:46:21 +04:00
|
|
|
|
|
|
|
|
|
Color? customBackgroundColor;
|
2011-12-21 10:19:31 +04:00
|
|
|
|
|
2011-12-25 00:34:03 +04:00
|
|
|
|
public virtual Color BackgroundColor {
|
2011-12-28 23:46:21 +04:00
|
|
|
|
get {
|
|
|
|
|
if (customBackgroundColor.HasValue)
|
|
|
|
|
return customBackgroundColor.Value;
|
|
|
|
|
|
2012-01-03 22:28:55 +04:00
|
|
|
|
return DataConverter.ToXwtColor (GetWidgetColor ());
|
2011-12-28 23:46:21 +04:00
|
|
|
|
}
|
|
|
|
|
set {
|
|
|
|
|
customBackgroundColor = value;
|
2012-01-03 22:28:55 +04:00
|
|
|
|
SetWidgetColor (value);
|
2011-12-28 23:46:21 +04:00
|
|
|
|
}
|
2011-12-25 00:34:03 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-01-03 22:28:55 +04:00
|
|
|
|
SWM.Color GetWidgetColor ()
|
|
|
|
|
{
|
|
|
|
|
if (Widget is Control) {
|
|
|
|
|
var control = (Control)Widget;
|
2012-03-22 04:29:24 +04:00
|
|
|
|
if (control.Background != null)
|
|
|
|
|
return ((SWM.SolidColorBrush)control.Background).Color;
|
|
|
|
|
} else if (Widget is SWC.Panel) {
|
2012-01-03 22:28:55 +04:00
|
|
|
|
var panel = (SWC.Panel)Widget;
|
2012-03-22 04:29:24 +04:00
|
|
|
|
if (panel.Background != null)
|
|
|
|
|
return ((SWM.SolidColorBrush)panel.Background).Color;
|
2012-01-03 22:28:55 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SystemColors.ControlColor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetWidgetColor (Color value)
|
|
|
|
|
{
|
|
|
|
|
if ((Widget is Control))
|
|
|
|
|
((Control)Widget).Background = ResPool.GetSolidBrush (value);
|
|
|
|
|
if ((Widget is System.Windows.Controls.Panel))
|
|
|
|
|
((SWC.Panel)Widget).Background = ResPool.GetSolidBrush (value);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-25 00:34:03 +04:00
|
|
|
|
public bool UsingCustomBackgroundColor {
|
2011-12-28 23:46:21 +04:00
|
|
|
|
get { return customBackgroundColor.HasValue; }
|
2011-12-25 00:34:03 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-12-30 22:05:40 +04:00
|
|
|
|
public virtual object Font {
|
2012-01-03 22:28:55 +04:00
|
|
|
|
get { return GetWidgetFont (); }
|
2011-12-30 22:05:40 +04:00
|
|
|
|
set {
|
2012-01-03 22:28:55 +04:00
|
|
|
|
SetWidgetFont ((FontData)value);
|
2011-12-30 22:05:40 +04:00
|
|
|
|
}
|
2011-12-25 00:34:03 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-01-03 22:28:55 +04:00
|
|
|
|
FontData GetWidgetFont ()
|
|
|
|
|
{
|
2012-04-02 21:29:49 +04:00
|
|
|
|
if (!(Widget is Control)) {
|
|
|
|
|
double size = FontBackendHandler.GetPointsFromPixels (SystemFonts.MessageFontSize, DPI);
|
|
|
|
|
|
|
|
|
|
return new FontData (SystemFonts.MessageFontFamily, size) {
|
|
|
|
|
Style = SystemFonts.MessageFontStyle,
|
|
|
|
|
Weight = SystemFonts.MessageFontWeight
|
|
|
|
|
};
|
|
|
|
|
}
|
2012-01-03 22:28:55 +04:00
|
|
|
|
|
|
|
|
|
return FontData.FromControl ((Control)Widget);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetWidgetFont (FontData font)
|
|
|
|
|
{
|
|
|
|
|
if (!(Widget is Control))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var control = (Control)Widget;
|
|
|
|
|
control.FontFamily = font.Family;
|
2012-04-02 21:29:49 +04:00
|
|
|
|
control.FontSize = FontBackendHandler.GetPixelsFromPoints (font.Size, DPI);
|
2012-01-03 22:28:55 +04:00
|
|
|
|
control.FontStyle = font.Style;
|
|
|
|
|
control.FontWeight = font.Weight;
|
|
|
|
|
control.FontStretch = font.Stretch;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 10:19:31 +04:00
|
|
|
|
public bool CanGetFocus {
|
|
|
|
|
get { return Widget.Focusable; }
|
|
|
|
|
set { Widget.Focusable = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool HasFocus {
|
|
|
|
|
get { return Widget.IsFocused; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetFocus ()
|
|
|
|
|
{
|
|
|
|
|
Widget.Focus ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual bool Sensitive {
|
|
|
|
|
get { return Widget.IsEnabled; }
|
|
|
|
|
set { Widget.IsEnabled = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Size Size {
|
|
|
|
|
get { return new Size (Widget.ActualWidth, Widget.ActualHeight); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual bool Visible {
|
|
|
|
|
get { return Widget.Visibility == Visibility.Visible; }
|
2012-04-24 01:57:03 +04:00
|
|
|
|
set { Widget.Visibility = value ? Visibility.Visible : Visibility.Collapsed; }
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-02-24 16:28:17 +04:00
|
|
|
|
public string TooltipText {
|
|
|
|
|
get { return Widget.ToolTip.ToString (); }
|
|
|
|
|
set { Widget.ToolTip = value; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-03 22:28:55 +04:00
|
|
|
|
public static FrameworkElement GetFrameworkElement (IWidgetBackend backend)
|
|
|
|
|
{
|
|
|
|
|
return backend == null ? null : (FrameworkElement)backend.NativeWidget;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 10:19:31 +04:00
|
|
|
|
public Point ConvertToScreenCoordinates (Point widgetCoordinates)
|
|
|
|
|
{
|
2012-03-24 02:20:00 +04:00
|
|
|
|
double wratio = WidthPixelRatio;
|
|
|
|
|
double hratio = HeightPixelRatio;
|
|
|
|
|
|
|
|
|
|
var p = Widget.PointToScreen (new System.Windows.Point (
|
|
|
|
|
widgetCoordinates.X / wratio, widgetCoordinates.Y / hratio));
|
2012-03-28 17:55:46 +04:00
|
|
|
|
|
2012-03-24 02:20:00 +04:00
|
|
|
|
return new Point (p.X * wratio, p.Y * hratio);
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-04-02 19:40:03 +04:00
|
|
|
|
SW.Size lastNaturalSize;
|
|
|
|
|
|
|
|
|
|
void GetWidgetDesiredSize (double availableWidth, double availableHeight, out SW.Size minSize, out SW.Size naturalSize)
|
2011-12-24 22:01:17 +04:00
|
|
|
|
{
|
2012-03-29 04:02:59 +04:00
|
|
|
|
// Calculates the desired size of widget.
|
|
|
|
|
|
2012-03-12 13:45:34 +04:00
|
|
|
|
if (!Widget.IsMeasureValid) {
|
2012-03-29 04:02:59 +04:00
|
|
|
|
try {
|
2012-04-02 19:40:03 +04:00
|
|
|
|
calculatingPreferredSize = true;
|
|
|
|
|
gettingNaturalSize = true;
|
|
|
|
|
Widget.Measure (new System.Windows.Size (availableWidth, availableHeight));
|
|
|
|
|
lastNaturalSize = Widget.DesiredSize;
|
|
|
|
|
gettingNaturalSize = false;
|
|
|
|
|
|
|
|
|
|
Widget.InvalidateMeasure ();
|
2012-03-29 04:02:59 +04:00
|
|
|
|
Widget.Measure (new System.Windows.Size (availableWidth, availableHeight));
|
|
|
|
|
}
|
|
|
|
|
finally {
|
|
|
|
|
calculatingPreferredSize = false;
|
2012-04-02 19:40:03 +04:00
|
|
|
|
gettingNaturalSize = false;
|
2012-03-29 04:02:59 +04:00
|
|
|
|
}
|
2012-03-12 13:45:34 +04:00
|
|
|
|
}
|
2012-04-02 19:40:03 +04:00
|
|
|
|
minSize = Widget.DesiredSize;
|
|
|
|
|
naturalSize = lastNaturalSize;
|
2012-03-29 04:02:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The GetPreferred* methods are called when the corresponding OnGetPreferred* methods in the
|
|
|
|
|
// XWT widget are not overriden, or if they are overriden and the new implementation calls
|
|
|
|
|
// base.OnGetPreferred*. For this reason, we have to ensure that the widget's MeasureOverride
|
|
|
|
|
// method doesn't end calling the frontend OnGetPreferred* methods. To avoid it we set
|
|
|
|
|
// the calculatingPreferredSize flag to true, and we check this flag in MeasureOverride
|
|
|
|
|
|
2011-12-21 10:19:31 +04:00
|
|
|
|
public virtual WidgetSize GetPreferredWidth ()
|
|
|
|
|
{
|
2012-04-02 19:40:03 +04:00
|
|
|
|
SW.Size minSize, natSize;
|
|
|
|
|
GetWidgetDesiredSize (Double.PositiveInfinity, Double.PositiveInfinity, out minSize, out natSize);
|
|
|
|
|
return new WidgetSize (minSize.Width * WidthPixelRatio, natSize.Width * WidthPixelRatio);
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual WidgetSize GetPreferredHeight ()
|
|
|
|
|
{
|
2012-04-02 19:40:03 +04:00
|
|
|
|
SW.Size minSize, natSize;
|
|
|
|
|
GetWidgetDesiredSize (Double.PositiveInfinity, Double.PositiveInfinity, out minSize, out natSize);
|
|
|
|
|
return new WidgetSize (minSize.Height * WidthPixelRatio, natSize.Height * HeightPixelRatio);
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual WidgetSize GetPreferredWidthForHeight (double height)
|
|
|
|
|
{
|
2012-04-02 19:40:03 +04:00
|
|
|
|
SW.Size minSize, natSize;
|
|
|
|
|
GetWidgetDesiredSize (Double.PositiveInfinity, height, out minSize, out natSize);
|
|
|
|
|
return new WidgetSize (minSize.Width * WidthPixelRatio, natSize.Width * WidthPixelRatio);
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual WidgetSize GetPreferredHeightForWidth (double width)
|
|
|
|
|
{
|
2012-04-02 19:40:03 +04:00
|
|
|
|
SW.Size minSize, natSize;
|
|
|
|
|
GetWidgetDesiredSize (width, Double.PositiveInfinity, out minSize, out natSize);
|
|
|
|
|
return new WidgetSize (minSize.Height * HeightPixelRatio, natSize.Height * HeightPixelRatio);
|
2012-03-29 04:02:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// A default implementation of MeasureOverride to be used by all WPF widgets
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="constraint">Size constraints</param>
|
|
|
|
|
/// <param name="wpfMeasure">Size returned by the base MeasureOverride</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public System.Windows.Size MeasureOverride (System.Windows.Size constraint, System.Windows.Size wpfMeasure)
|
|
|
|
|
{
|
|
|
|
|
// Calculate the natural size, if that's what is being measured
|
|
|
|
|
|
|
|
|
|
if (gettingNaturalSize) {
|
|
|
|
|
var defNaturalSize = eventSink.GetDefaultNaturalSize ();
|
|
|
|
|
|
|
|
|
|
// -2 means use the WPF default, -1 use the XWT default, any other other value is used as custom natural size
|
|
|
|
|
var nw = DefaultNaturalWidth;
|
2012-04-02 19:40:03 +04:00
|
|
|
|
if (nw == -1) {
|
2012-03-29 04:02:59 +04:00
|
|
|
|
nw = defNaturalSize.Width;
|
|
|
|
|
if (nw == 0)
|
|
|
|
|
nw = wpfMeasure.Width;
|
2012-04-02 19:40:03 +04:00
|
|
|
|
wpfMeasure.Width = nw;
|
2012-03-29 04:02:59 +04:00
|
|
|
|
}
|
2012-04-02 19:40:03 +04:00
|
|
|
|
else if (nw != -2)
|
|
|
|
|
wpfMeasure.Width = nw;
|
2012-03-29 04:02:59 +04:00
|
|
|
|
|
|
|
|
|
var nh = DefaultNaturalHeight;
|
2012-04-02 19:40:03 +04:00
|
|
|
|
if (nh == -1) {
|
2012-03-29 04:02:59 +04:00
|
|
|
|
nh = defNaturalSize.Height;
|
|
|
|
|
if (nh == 0)
|
|
|
|
|
nh = wpfMeasure.Height;
|
2012-04-02 19:40:03 +04:00
|
|
|
|
wpfMeasure.Height = nh;
|
2012-03-29 04:02:59 +04:00
|
|
|
|
}
|
2012-04-02 19:40:03 +04:00
|
|
|
|
else if (nh != -2)
|
|
|
|
|
wpfMeasure.Height = nh;
|
2012-03-29 04:02:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we are calculating the default preferred size of the widget we end here.
|
|
|
|
|
// See note above about when GetPreferred* methods are called.
|
|
|
|
|
if (calculatingPreferredSize)
|
|
|
|
|
return wpfMeasure;
|
|
|
|
|
|
|
|
|
|
Toolkit.Invoke (delegate
|
|
|
|
|
{
|
|
|
|
|
if (eventSink.GetSizeRequestMode () == SizeRequestMode.HeightForWidth) {
|
|
|
|
|
// Calculate the preferred width through the frontend, if there is an overriden OnGetPreferredWidth
|
|
|
|
|
if ((enabledEvents & WidgetEvent.PreferredWidthCheck) != 0) {
|
|
|
|
|
var ws = eventSink.OnGetPreferredWidth ();
|
|
|
|
|
wpfMeasure.Width = gettingNaturalSize ? ws.NaturalSize : ws.MinSize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now calculate the preferred height for that width, also using the override if available
|
|
|
|
|
if ((enabledEvents & WidgetEvent.PreferredHeightForWidthCheck) != 0) {
|
|
|
|
|
var ws = eventSink.OnGetPreferredHeightForWidth (wpfMeasure.Width);
|
|
|
|
|
wpfMeasure.Height = gettingNaturalSize ? ws.NaturalSize : ws.MinSize;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// Calculate the preferred height through the frontend, if there is an overriden OnGetPreferredHeight
|
|
|
|
|
if ((enabledEvents & WidgetEvent.PreferredHeightCheck) != 0) {
|
|
|
|
|
var ws = eventSink.OnGetPreferredHeight ();
|
|
|
|
|
wpfMeasure.Height = gettingNaturalSize ? ws.NaturalSize : ws.MinSize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now calculate the preferred width for that height, also using the override if available
|
|
|
|
|
if ((enabledEvents & WidgetEvent.PreferredWidthForHeightCheck) != 0) {
|
|
|
|
|
var ws = eventSink.OnGetPreferredWidthForHeight (wpfMeasure.Height);
|
|
|
|
|
wpfMeasure.Width = gettingNaturalSize ? ws.NaturalSize : ws.MinSize;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return wpfMeasure;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Natural width for the widget. It can be any arbitrary custom value,
|
|
|
|
|
/// or -1 if the XWT defined default has to be used,
|
|
|
|
|
/// or -2 if the WPF desired size has to be used (this is the default)
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected virtual double DefaultNaturalWidth {
|
|
|
|
|
get { return -2; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Natural width for the widget. It can be any arbitrary custom value,
|
|
|
|
|
/// or -1 if the XWT defined default has to be used,
|
|
|
|
|
/// or -2 if the WPF desired size has to be used (this is the default)
|
|
|
|
|
/// </summary>
|
|
|
|
|
protected virtual double DefaultNaturalHeight
|
|
|
|
|
{
|
|
|
|
|
get { return -2; }
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-12-25 00:34:03 +04:00
|
|
|
|
public void SetMinSize (double width, double height)
|
|
|
|
|
{
|
2012-03-08 02:57:58 +04:00
|
|
|
|
if (width == -1)
|
|
|
|
|
Widget.ClearValue (FrameworkElement.MinWidthProperty);
|
|
|
|
|
else
|
2012-03-09 23:40:40 +04:00
|
|
|
|
Widget.MinWidth = width / WidthPixelRatio;
|
2012-03-08 02:57:58 +04:00
|
|
|
|
|
|
|
|
|
if (height == -1)
|
|
|
|
|
Widget.ClearValue (FrameworkElement.MinHeightProperty);
|
|
|
|
|
else
|
2012-03-09 23:40:40 +04:00
|
|
|
|
Widget.MinHeight = height / HeightPixelRatio;
|
2011-12-25 00:34:03 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-01-06 04:38:47 +04:00
|
|
|
|
public void SetNaturalSize (double width, double height)
|
|
|
|
|
{
|
2012-03-22 04:43:08 +04:00
|
|
|
|
if (width == -1)
|
|
|
|
|
Widget.ClearValue (FrameworkElement.WidthProperty);
|
|
|
|
|
else
|
|
|
|
|
Widget.Width = width / WidthPixelRatio;
|
|
|
|
|
|
|
|
|
|
if (height == -1)
|
|
|
|
|
Widget.ClearValue (FrameworkElement.HeightProperty);
|
|
|
|
|
else
|
|
|
|
|
Widget.Height = height / HeightPixelRatio;
|
2012-01-06 04:38:47 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-12 19:23:09 +04:00
|
|
|
|
public void SetCursor (CursorType cursor)
|
|
|
|
|
{
|
2012-04-04 02:41:29 +04:00
|
|
|
|
if (cursor == CursorType.Arrow)
|
|
|
|
|
Widget.Cursor = Cursors.Arrow;
|
|
|
|
|
else if (cursor == CursorType.Crosshair)
|
|
|
|
|
Widget.Cursor = Cursors.Cross;
|
|
|
|
|
else if (cursor == CursorType.Hand)
|
|
|
|
|
Widget.Cursor = Cursors.Hand;
|
|
|
|
|
else if (cursor == CursorType.IBeam)
|
|
|
|
|
Widget.Cursor = Cursors.IBeam;
|
|
|
|
|
else if (cursor == CursorType.ResizeDown)
|
2012-04-04 11:36:19 +04:00
|
|
|
|
Widget.Cursor = Cursors.SizeNS;
|
2012-04-04 02:41:29 +04:00
|
|
|
|
else if (cursor == CursorType.ResizeUp)
|
2012-04-04 11:36:19 +04:00
|
|
|
|
Widget.Cursor = Cursors.SizeNS;
|
2012-04-04 02:41:29 +04:00
|
|
|
|
else if (cursor == CursorType.ResizeUpDown)
|
|
|
|
|
Widget.Cursor = Cursors.SizeNS;
|
|
|
|
|
else if (cursor == CursorType.ResizeLeft)
|
2012-04-04 11:36:19 +04:00
|
|
|
|
Widget.Cursor = Cursors.SizeWE;
|
2012-04-04 02:41:29 +04:00
|
|
|
|
else if (cursor == CursorType.ResizeRight)
|
2012-04-04 11:36:19 +04:00
|
|
|
|
Widget.Cursor = Cursors.SizeWE;
|
2012-04-04 02:41:29 +04:00
|
|
|
|
else if (cursor == CursorType.ResizeLeftRight)
|
|
|
|
|
widget.Cursor = Cursors.SizeWE;
|
2012-03-12 19:23:09 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 10:19:31 +04:00
|
|
|
|
public virtual void UpdateLayout ()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-02 23:43:05 +04:00
|
|
|
|
public override void EnableEvent (object eventId)
|
2011-12-21 10:19:31 +04:00
|
|
|
|
{
|
|
|
|
|
if (eventId is WidgetEvent) {
|
2012-03-28 17:55:46 +04:00
|
|
|
|
var ev = (WidgetEvent)eventId;
|
|
|
|
|
switch (ev) {
|
2011-12-21 10:19:31 +04:00
|
|
|
|
case WidgetEvent.DragLeave:
|
|
|
|
|
Widget.DragLeave += WidgetDragLeaveHandler;
|
|
|
|
|
break;
|
|
|
|
|
case WidgetEvent.KeyPressed:
|
|
|
|
|
Widget.KeyDown += WidgetKeyDownHandler;
|
|
|
|
|
break;
|
|
|
|
|
case WidgetEvent.KeyReleased:
|
|
|
|
|
Widget.KeyDown += WidgetKeyUpHandler;
|
|
|
|
|
break;
|
2012-03-13 14:13:32 +04:00
|
|
|
|
case WidgetEvent.ButtonPressed:
|
|
|
|
|
Widget.MouseDown += WidgetMouseDownHandler;
|
|
|
|
|
break;
|
|
|
|
|
case WidgetEvent.ButtonReleased:
|
|
|
|
|
Widget.MouseUp += WidgetMouseUpHandler;
|
|
|
|
|
break;
|
2011-12-25 00:34:03 +04:00
|
|
|
|
case WidgetEvent.GotFocus:
|
|
|
|
|
Widget.GotFocus += WidgetGotFocusHandler;
|
|
|
|
|
break;
|
|
|
|
|
case WidgetEvent.LostFocus:
|
|
|
|
|
Widget.LostFocus += WidgetLostFocusHandler;
|
|
|
|
|
break;
|
2012-03-10 00:46:39 +04:00
|
|
|
|
case WidgetEvent.MouseEntered:
|
|
|
|
|
Widget.MouseEnter += WidgetMouseEnteredHandler;
|
|
|
|
|
break;
|
|
|
|
|
case WidgetEvent.MouseExited:
|
|
|
|
|
Widget.MouseLeave += WidgetMouseExitedHandler;
|
|
|
|
|
break;
|
2012-03-23 21:44:50 +04:00
|
|
|
|
case WidgetEvent.MouseMoved:
|
|
|
|
|
Widget.MouseMove += WidgetMouseMoveHandler;
|
|
|
|
|
break;
|
2012-03-16 21:09:35 +04:00
|
|
|
|
case WidgetEvent.BoundsChanged:
|
|
|
|
|
Widget.SizeChanged += WidgetOnSizeChanged;
|
|
|
|
|
break;
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
2012-03-28 17:55:46 +04:00
|
|
|
|
|
|
|
|
|
if ((ev & dragDropEvents) != 0 && (enabledEvents & dragDropEvents) == 0) {
|
|
|
|
|
// Enabling a drag&drop event for the first time
|
|
|
|
|
Widget.DragOver += WidgetDragOverHandler;
|
|
|
|
|
Widget.Drop += WidgetDropHandler;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enabledEvents |= ev;
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-02 23:43:05 +04:00
|
|
|
|
public override void DisableEvent (object eventId)
|
2011-12-21 10:19:31 +04:00
|
|
|
|
{
|
|
|
|
|
if (eventId is WidgetEvent) {
|
2012-03-28 17:55:46 +04:00
|
|
|
|
var ev = (WidgetEvent)eventId;
|
|
|
|
|
switch (ev) {
|
2011-12-21 10:19:31 +04:00
|
|
|
|
case WidgetEvent.DragLeave:
|
|
|
|
|
Widget.DragLeave -= WidgetDragLeaveHandler;
|
|
|
|
|
break;
|
|
|
|
|
case WidgetEvent.KeyPressed:
|
|
|
|
|
Widget.KeyDown -= WidgetKeyDownHandler;
|
|
|
|
|
break;
|
|
|
|
|
case WidgetEvent.KeyReleased:
|
|
|
|
|
Widget.KeyUp -= WidgetKeyUpHandler;
|
|
|
|
|
break;
|
2012-03-13 14:13:32 +04:00
|
|
|
|
case WidgetEvent.ButtonPressed:
|
|
|
|
|
Widget.MouseDown -= WidgetMouseDownHandler;
|
|
|
|
|
break;
|
|
|
|
|
case WidgetEvent.ButtonReleased:
|
|
|
|
|
Widget.MouseUp -= WidgetMouseUpHandler;
|
|
|
|
|
break;
|
2012-03-10 00:46:39 +04:00
|
|
|
|
case WidgetEvent.MouseEntered:
|
|
|
|
|
Widget.MouseEnter -= WidgetMouseEnteredHandler;
|
|
|
|
|
break;
|
|
|
|
|
case WidgetEvent.MouseExited:
|
|
|
|
|
Widget.MouseLeave -= WidgetMouseExitedHandler;
|
|
|
|
|
break;
|
2012-03-23 21:44:50 +04:00
|
|
|
|
case WidgetEvent.MouseMoved:
|
|
|
|
|
Widget.MouseMove -= WidgetMouseMoveHandler;
|
|
|
|
|
break;
|
2012-03-16 21:09:35 +04:00
|
|
|
|
case WidgetEvent.BoundsChanged:
|
|
|
|
|
Widget.SizeChanged -= WidgetOnSizeChanged;
|
|
|
|
|
break;
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
2012-03-28 17:55:46 +04:00
|
|
|
|
|
|
|
|
|
enabledEvents &= ~ev;
|
|
|
|
|
|
|
|
|
|
if ((ev & dragDropEvents) != 0 && (enabledEvents & dragDropEvents) == 0) {
|
|
|
|
|
// All drag&drop events have been disabled
|
|
|
|
|
Widget.DragOver -= WidgetDragOverHandler;
|
|
|
|
|
Widget.Drop -= WidgetDropHandler;
|
|
|
|
|
}
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-09 23:40:40 +04:00
|
|
|
|
protected double WidthPixelRatio
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
PresentationSource source = PresentationSource.FromVisual (Widget);
|
|
|
|
|
if (source == null)
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
Matrix m = source.CompositionTarget.TransformToDevice;
|
|
|
|
|
return m.M11;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected double HeightPixelRatio
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
PresentationSource source = PresentationSource.FromVisual (Widget);
|
|
|
|
|
if (source == null)
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
Matrix m = source.CompositionTarget.TransformToDevice;
|
|
|
|
|
return m.M22;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-02 21:29:49 +04:00
|
|
|
|
protected double DPI
|
|
|
|
|
{
|
|
|
|
|
get { return WidthPixelRatio * 96; }
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 10:19:31 +04:00
|
|
|
|
void WidgetKeyDownHandler (object sender, System.Windows.Input.KeyEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
KeyEventArgs args;
|
2012-04-23 22:16:11 +04:00
|
|
|
|
if (MapToXwtKeyArgs (e, out args)) {
|
2012-01-06 07:13:03 +04:00
|
|
|
|
Toolkit.Invoke (delegate {
|
|
|
|
|
eventSink.OnKeyPressed (args);
|
|
|
|
|
});
|
2012-05-10 15:25:56 +04:00
|
|
|
|
if (args.Handled)
|
2012-04-23 22:16:11 +04:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
}
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WidgetKeyUpHandler (object sender, System.Windows.Input.KeyEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
KeyEventArgs args;
|
2012-04-23 22:16:11 +04:00
|
|
|
|
if (MapToXwtKeyArgs (e, out args)) {
|
2012-01-06 07:13:03 +04:00
|
|
|
|
Toolkit.Invoke (delegate {
|
|
|
|
|
eventSink.OnKeyReleased (args);
|
|
|
|
|
});
|
2012-05-10 15:25:56 +04:00
|
|
|
|
if (args.Handled)
|
2012-04-23 22:16:11 +04:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
}
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MapToXwtKeyArgs (System.Windows.Input.KeyEventArgs e, out KeyEventArgs result)
|
|
|
|
|
{
|
|
|
|
|
result = null;
|
|
|
|
|
|
|
|
|
|
var key = KeyboardUtil.TranslateToXwtKey (e.Key);
|
|
|
|
|
if ((int)key == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
result = new KeyEventArgs (key, KeyboardUtil.GetModifiers (), e.IsRepeat, e.Timestamp);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-13 14:13:32 +04:00
|
|
|
|
void WidgetMouseDownHandler (object o, MouseButtonEventArgs e)
|
|
|
|
|
{
|
2012-05-10 15:25:56 +04:00
|
|
|
|
var args = ToXwtButtonArgs (e);
|
2012-03-13 14:13:32 +04:00
|
|
|
|
Toolkit.Invoke (delegate () {
|
2012-05-10 15:25:56 +04:00
|
|
|
|
eventSink.OnButtonPressed (args);
|
2012-03-13 14:13:32 +04:00
|
|
|
|
});
|
2012-05-10 15:25:56 +04:00
|
|
|
|
if (args.Handled)
|
|
|
|
|
e.Handled = true;
|
2012-03-13 14:13:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WidgetMouseUpHandler (object o, MouseButtonEventArgs e)
|
|
|
|
|
{
|
2012-05-10 15:25:56 +04:00
|
|
|
|
var args = ToXwtButtonArgs (e);
|
2012-03-13 14:13:32 +04:00
|
|
|
|
Toolkit.Invoke (delegate () {
|
2012-05-10 15:25:56 +04:00
|
|
|
|
eventSink.OnButtonReleased (args);
|
2012-03-13 14:13:32 +04:00
|
|
|
|
});
|
2012-05-10 15:25:56 +04:00
|
|
|
|
if (args.Handled)
|
|
|
|
|
e.Handled = true;
|
2012-03-13 14:13:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ButtonEventArgs ToXwtButtonArgs (MouseButtonEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var pos = e.GetPosition (Widget);
|
|
|
|
|
return new ButtonEventArgs () {
|
2012-03-24 02:20:00 +04:00
|
|
|
|
X = pos.X * WidthPixelRatio,
|
|
|
|
|
Y = pos.Y * HeightPixelRatio,
|
2012-03-13 14:13:32 +04:00
|
|
|
|
MultiplePress = e.ClickCount,
|
|
|
|
|
Button = e.ChangedButton.ToXwtButton ()
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-25 00:34:03 +04:00
|
|
|
|
void WidgetGotFocusHandler (object o, RoutedEventArgs e)
|
|
|
|
|
{
|
2012-04-24 01:57:28 +04:00
|
|
|
|
Toolkit.Invoke (this.eventSink.OnGotFocus);
|
2011-12-25 00:34:03 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WidgetLostFocusHandler (object o, RoutedEventArgs e)
|
|
|
|
|
{
|
2012-04-24 01:57:28 +04:00
|
|
|
|
Toolkit.Invoke (eventSink.OnLostFocus);
|
2011-12-25 00:34:03 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-04-01 03:50:31 +04:00
|
|
|
|
DragDropData DragDropInfo {
|
|
|
|
|
get {
|
|
|
|
|
if (dragDropInfo == null)
|
|
|
|
|
dragDropInfo = new DragDropData ();
|
|
|
|
|
|
|
|
|
|
return dragDropInfo;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-07 02:33:32 +04:00
|
|
|
|
private static ImageAdorner Adorner;
|
|
|
|
|
private static AdornerLayer AdornedLayer;
|
|
|
|
|
private static System.Windows.Window AdornedWindow;
|
|
|
|
|
|
|
|
|
|
private SW.Window GetParentWindow()
|
|
|
|
|
{
|
|
|
|
|
FrameworkElement current = Widget;
|
|
|
|
|
while (current != null) {
|
|
|
|
|
if (current is SW.Window)
|
|
|
|
|
return (SW.Window)current;
|
|
|
|
|
|
|
|
|
|
current = current.Parent as FrameworkElement;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2012-04-24 22:43:52 +04:00
|
|
|
|
|
2012-02-24 16:28:17 +04:00
|
|
|
|
public void DragStart (DragStartData data)
|
2011-12-21 10:19:31 +04:00
|
|
|
|
{
|
2012-03-28 17:55:46 +04:00
|
|
|
|
if (data.Data == null)
|
|
|
|
|
throw new ArgumentNullException ("data");
|
2012-04-24 01:56:34 +04:00
|
|
|
|
|
2012-04-05 21:50:24 +04:00
|
|
|
|
DataObject dataObj = data.Data.ToDataObject();
|
2012-04-04 17:25:37 +04:00
|
|
|
|
|
2012-04-24 01:56:34 +04:00
|
|
|
|
if (data.ImageBackend != null) {
|
2012-06-07 02:33:32 +04:00
|
|
|
|
AdornedWindow = GetParentWindow ();
|
|
|
|
|
AdornedWindow.AllowDrop = true;
|
|
|
|
|
|
|
|
|
|
var e = (UIElement)AdornedWindow.Content;
|
|
|
|
|
|
|
|
|
|
Adorner = new ImageAdorner (e, data.ImageBackend);
|
|
|
|
|
|
|
|
|
|
AdornedLayer = AdornerLayer.GetAdornerLayer (e);
|
|
|
|
|
AdornedLayer.Add (Adorner);
|
|
|
|
|
|
|
|
|
|
AdornedWindow.DragOver += AdornedWindowOnDragOver;
|
2012-04-24 01:56:34 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-06-07 01:20:07 +04:00
|
|
|
|
Widget.Dispatcher.BeginInvoke ((Action)(() => {
|
|
|
|
|
var effect = DragDrop.DoDragDrop (Widget, dataObj, data.DragAction.ToWpfDropEffect ());
|
|
|
|
|
|
|
|
|
|
Toolkit.Invoke (delegate {
|
|
|
|
|
this.eventSink.OnDragFinished (new DragFinishedEventArgs (effect == DragDropEffects.Move));
|
|
|
|
|
});
|
|
|
|
|
|
2012-06-07 02:33:32 +04:00
|
|
|
|
if (Adorner != null) {
|
|
|
|
|
AdornedLayer.Remove (Adorner);
|
|
|
|
|
AdornedLayer = null;
|
|
|
|
|
Adorner = null;
|
|
|
|
|
|
|
|
|
|
AdornedWindow.AllowDrop = false;
|
|
|
|
|
AdornedWindow.DragOver -= AdornedWindowOnDragOver;
|
|
|
|
|
AdornedWindow = null;
|
2012-06-07 01:20:07 +04:00
|
|
|
|
}
|
|
|
|
|
}));
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-06-07 02:33:32 +04:00
|
|
|
|
private void AdornedWindowOnDragOver (object sender, System.Windows.DragEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
WidgetDragOverHandler (sender, e);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-24 16:28:17 +04:00
|
|
|
|
public void SetDragTarget (TransferDataType [] types, DragDropAction dragAction)
|
2011-12-21 10:19:31 +04:00
|
|
|
|
{
|
2012-04-04 17:25:37 +04:00
|
|
|
|
DragDropInfo.TargetTypes = types == null ? new TransferDataType [0] : types;
|
2012-03-28 17:55:46 +04:00
|
|
|
|
Widget.AllowDrop = true;
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-02-24 16:28:17 +04:00
|
|
|
|
public void SetDragSource (TransferDataType [] types, DragDropAction dragAction)
|
2011-12-21 10:19:31 +04:00
|
|
|
|
{
|
2012-04-01 03:50:31 +04:00
|
|
|
|
if (DragDropInfo.AutodetectDrag)
|
|
|
|
|
return; // Drag auto detect has been already activated.
|
|
|
|
|
|
|
|
|
|
DragDropInfo.AutodetectDrag = true;
|
|
|
|
|
Widget.MouseDown += WidgetMouseDownForDragHandler;
|
|
|
|
|
Widget.MouseUp += WidgetMouseUpForDragHandler;
|
|
|
|
|
Widget.MouseMove += WidgetMouseMoveForDragHandler;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WidgetMouseDownForDragHandler (object o, MouseButtonEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if ((enabledEvents & WidgetEvent.DragStarted) == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var width = SystemParameters.MinimumHorizontalDragDistance;
|
|
|
|
|
var height = SystemParameters.MinimumVerticalDragDistance;
|
|
|
|
|
var loc = e.GetPosition (Widget);
|
|
|
|
|
DragDropInfo.DragRect = new Rect (loc.X - width / 2, loc.Y - height / 2, width, height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WidgetMouseUpForDragHandler (object o, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
DragDropInfo.DragRect = Rect.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WidgetMouseMoveForDragHandler (object o, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if ((enabledEvents & WidgetEvent.DragStarted) == 0)
|
|
|
|
|
return;
|
|
|
|
|
if (e.LeftButton != MouseButtonState.Pressed)
|
|
|
|
|
return;
|
|
|
|
|
if (DragDropInfo.DragRect.IsEmpty || DragDropInfo.DragRect.Contains (e.GetPosition (Widget)))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
DragStartData dragData = null;
|
|
|
|
|
Toolkit.Invoke (delegate {
|
|
|
|
|
dragData = eventSink.OnDragStarted ();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (dragData != null)
|
|
|
|
|
DragStart (dragData);
|
|
|
|
|
|
|
|
|
|
DragDropInfo.DragRect = Rect.Empty;
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-28 17:55:46 +04:00
|
|
|
|
static DragDropAction DetectDragAction (DragDropKeyStates keys)
|
|
|
|
|
{
|
|
|
|
|
if ((keys & DragDropKeyStates.ControlKey) == DragDropKeyStates.ControlKey) {
|
|
|
|
|
if ((keys & DragDropKeyStates.ShiftKey) == DragDropKeyStates.ShiftKey)
|
|
|
|
|
return DragDropAction.Link;
|
|
|
|
|
else
|
|
|
|
|
return DragDropAction.Copy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DragDropAction.Move;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-04 17:25:37 +04:00
|
|
|
|
static void FillDataStore (TransferDataStore store, IDataObject data, TransferDataType [] types)
|
2012-03-28 17:55:46 +04:00
|
|
|
|
{
|
2012-04-04 17:25:37 +04:00
|
|
|
|
foreach (var type in types) {
|
2012-04-09 22:25:05 +04:00
|
|
|
|
string format = type.ToWpfDataFormat ();
|
2012-04-19 20:04:27 +04:00
|
|
|
|
if (!data.GetDataPresent (format)) {
|
|
|
|
|
// This is a workaround to support type names which don't include the assembly name.
|
|
|
|
|
// It eases integration with Windows DND.
|
|
|
|
|
format = NormalizeTypeName (format);
|
|
|
|
|
if (!data.GetDataPresent (format))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2012-04-04 17:25:37 +04:00
|
|
|
|
|
|
|
|
|
var value = data.GetData (format);
|
|
|
|
|
if (type == TransferDataType.Text)
|
|
|
|
|
store.AddText ((string)value);
|
|
|
|
|
else if (type == TransferDataType.Uri) {
|
|
|
|
|
var uris = ((string [])value).Select (f => new Uri (f)).ToArray ();
|
|
|
|
|
store.AddUris (uris);
|
2012-04-12 20:10:54 +04:00
|
|
|
|
} else if (value is byte[])
|
|
|
|
|
store.AddValue (type, (byte[]) value);
|
|
|
|
|
else
|
|
|
|
|
store.AddValue (type, value);
|
2012-03-28 17:55:46 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-19 20:04:27 +04:00
|
|
|
|
static string NormalizeTypeName (string dataType)
|
|
|
|
|
{
|
|
|
|
|
// If the string is a fully qualified type name, strip the assembly name
|
|
|
|
|
int i = dataType.IndexOf (',');
|
|
|
|
|
if (i == -1)
|
|
|
|
|
return dataType;
|
|
|
|
|
string asmName = dataType.Substring (i + 1).Trim ();
|
|
|
|
|
try {
|
|
|
|
|
new System.Reflection.AssemblyName (asmName);
|
|
|
|
|
}
|
|
|
|
|
catch {
|
|
|
|
|
return dataType;
|
|
|
|
|
}
|
|
|
|
|
return dataType.Substring (0, i).Trim ();
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-28 17:55:46 +04:00
|
|
|
|
void WidgetDragOverHandler (object sender, System.Windows.DragEventArgs e)
|
|
|
|
|
{
|
2012-04-09 22:25:05 +04:00
|
|
|
|
var types = e.Data.GetFormats ().Select (t => t.ToXwtTransferType ()).ToArray ();
|
2012-03-28 17:55:46 +04:00
|
|
|
|
var pos = e.GetPosition (Widget).ToXwtPoint ();
|
|
|
|
|
var proposedAction = DetectDragAction (e.KeyStates);
|
|
|
|
|
|
|
|
|
|
e.Handled = true; // Prevent default handlers from being used.
|
|
|
|
|
|
2012-06-07 02:33:32 +04:00
|
|
|
|
if (Adorner != null) {
|
|
|
|
|
var w = GetParentWindow ();
|
|
|
|
|
var v = (UIElement)w.Content;
|
|
|
|
|
|
|
|
|
|
if (w != AdornedWindow) {
|
|
|
|
|
AdornedLayer.Remove (Adorner);
|
|
|
|
|
|
|
|
|
|
AdornedWindow.AllowDrop = false;
|
|
|
|
|
AdornedWindow.DragOver -= AdornedWindowOnDragOver;
|
|
|
|
|
|
|
|
|
|
AdornedWindow = w;
|
|
|
|
|
AdornedWindow.AllowDrop = true;
|
|
|
|
|
AdornedWindow.DragOver += AdornedWindowOnDragOver;
|
|
|
|
|
|
|
|
|
|
AdornedLayer = AdornerLayer.GetAdornerLayer (v);
|
|
|
|
|
AdornedLayer.Add (Adorner);
|
2012-04-24 22:43:52 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-06-07 02:33:32 +04:00
|
|
|
|
Adorner.Offset = e.GetPosition (v);
|
2012-04-24 22:43:52 +04:00
|
|
|
|
}
|
2012-04-24 01:56:34 +04:00
|
|
|
|
|
2012-03-28 17:55:46 +04:00
|
|
|
|
if ((enabledEvents & WidgetEvent.DragOverCheck) > 0) {
|
|
|
|
|
var checkArgs = new DragOverCheckEventArgs (pos, types, proposedAction);
|
|
|
|
|
Toolkit.Invoke (delegate {
|
|
|
|
|
eventSink.OnDragOverCheck (checkArgs);
|
|
|
|
|
});
|
|
|
|
|
if (checkArgs.AllowedAction == DragDropAction.None) {
|
|
|
|
|
e.Effects = currentDragEffect = DragDropEffects.None;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (checkArgs.AllowedAction != DragDropAction.Default) {
|
|
|
|
|
e.Effects = currentDragEffect = checkArgs.AllowedAction.ToWpfDropEffect ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((enabledEvents & WidgetEvent.DragOver) > 0) {
|
|
|
|
|
var store = new TransferDataStore ();
|
2012-04-04 17:25:37 +04:00
|
|
|
|
FillDataStore (store, e.Data, DragDropInfo.TargetTypes);
|
2012-03-28 17:55:46 +04:00
|
|
|
|
|
|
|
|
|
var args = new DragOverEventArgs (pos, store, proposedAction);
|
|
|
|
|
Toolkit.Invoke (delegate {
|
|
|
|
|
eventSink.OnDragOver (args);
|
|
|
|
|
});
|
|
|
|
|
if (args.AllowedAction == DragDropAction.None) {
|
|
|
|
|
e.Effects = currentDragEffect = DragDropEffects.None;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (args.AllowedAction != DragDropAction.Default) {
|
|
|
|
|
e.Effects = currentDragEffect = args.AllowedAction.ToWpfDropEffect ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e.Effects = currentDragEffect = proposedAction.ToWpfDropEffect ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WidgetDropHandler (object sender, System.Windows.DragEventArgs e)
|
|
|
|
|
{
|
2012-04-09 20:30:51 +04:00
|
|
|
|
WidgetDragLeaveHandler (sender, e);
|
|
|
|
|
|
2012-04-09 22:25:05 +04:00
|
|
|
|
var types = e.Data.GetFormats ().Select (t => t.ToXwtTransferType ()).ToArray ();
|
2012-03-28 17:55:46 +04:00
|
|
|
|
var pos = e.GetPosition (Widget).ToXwtPoint ();
|
|
|
|
|
var actualEffect = currentDragEffect;
|
|
|
|
|
|
|
|
|
|
e.Handled = true; // Prevent default handlers from being used.
|
2012-06-07 00:58:50 +04:00
|
|
|
|
e.Effects = DragDropEffects.None;
|
2012-03-28 17:55:46 +04:00
|
|
|
|
|
|
|
|
|
if ((enabledEvents & WidgetEvent.DragDropCheck) > 0) {
|
|
|
|
|
var checkArgs = new DragCheckEventArgs (pos, types, actualEffect.ToXwtDropAction ());
|
|
|
|
|
bool res = Toolkit.Invoke (delegate {
|
|
|
|
|
eventSink.OnDragDropCheck (checkArgs);
|
|
|
|
|
});
|
2012-04-05 21:50:24 +04:00
|
|
|
|
|
2012-03-28 17:55:46 +04:00
|
|
|
|
if (checkArgs.Result == DragDropResult.Canceled || !res) {
|
|
|
|
|
e.Effects = DragDropEffects.None;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((enabledEvents & WidgetEvent.DragDrop) > 0) {
|
|
|
|
|
var store = new TransferDataStore ();
|
2012-04-04 17:25:37 +04:00
|
|
|
|
FillDataStore (store, e.Data, DragDropInfo.TargetTypes);
|
2012-03-28 17:55:46 +04:00
|
|
|
|
|
|
|
|
|
var args = new DragEventArgs (pos, store, actualEffect.ToXwtDropAction ());
|
|
|
|
|
Toolkit.Invoke (delegate {
|
|
|
|
|
eventSink.OnDragDrop (args);
|
|
|
|
|
});
|
|
|
|
|
|
2012-06-07 01:20:07 +04:00
|
|
|
|
if (args.Success)
|
|
|
|
|
e.Effects = actualEffect;
|
2012-03-28 17:55:46 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 10:19:31 +04:00
|
|
|
|
void WidgetDragLeaveHandler (object sender, System.Windows.DragEventArgs e)
|
|
|
|
|
{
|
2012-01-06 07:13:03 +04:00
|
|
|
|
Toolkit.Invoke (delegate {
|
|
|
|
|
eventSink.OnDragLeave (EventArgs.Empty);
|
|
|
|
|
});
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
2012-03-10 00:46:39 +04:00
|
|
|
|
|
|
|
|
|
private void WidgetMouseEnteredHandler (object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Toolkit.Invoke (eventSink.OnMouseEntered);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void WidgetMouseExitedHandler (object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Toolkit.Invoke (eventSink.OnMouseExited);
|
|
|
|
|
}
|
2012-03-16 21:09:35 +04:00
|
|
|
|
|
2012-03-23 21:44:50 +04:00
|
|
|
|
private void WidgetMouseMoveHandler (object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Toolkit.Invoke (() => {
|
|
|
|
|
var p = e.GetPosition (Widget);
|
2012-03-24 02:12:50 +04:00
|
|
|
|
eventSink.OnMouseMoved (new MouseMovedEventArgs (
|
|
|
|
|
e.Timestamp, p.X * WidthPixelRatio, p.Y * HeightPixelRatio));
|
2012-03-23 21:44:50 +04:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-16 21:09:35 +04:00
|
|
|
|
private void WidgetOnSizeChanged (object sender, SizeChangedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (Widget.IsVisible)
|
|
|
|
|
Toolkit.Invoke (this.eventSink.OnBoundsChanged);
|
|
|
|
|
}
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|
2012-01-06 04:38:47 +04:00
|
|
|
|
|
|
|
|
|
public interface IWpfWidgetBackend
|
|
|
|
|
{
|
|
|
|
|
FrameworkElement Widget { get; }
|
|
|
|
|
}
|
2012-03-29 04:02:59 +04:00
|
|
|
|
|
|
|
|
|
public interface IWpfWidget
|
|
|
|
|
{
|
|
|
|
|
WidgetBackend Backend { get; set; }
|
|
|
|
|
}
|
2011-12-21 10:19:31 +04:00
|
|
|
|
}
|