Horizontal Flip Transform in Silverlight? - silverlight

I was wondering what is the best way to flip an element horizontally in silverlight.
What I've tried so far:
1- Scale transformation: the problem this approach has is that I need to hardcode the width of the element to translate it after setting scale=-1; this makes it hard to implement (for many elements)
<ScaleTransform CenterX="240" ScaleX="-1" />
2- Plane projection: the problem with this one is that even mouse gestures are reversed! this makes it so impossible to use.
<PlaneProjection RotationY="-180" />
[NOTE] By reversed mouse gesture I mean: when applying plane projection, then dragging mouse to left is interpreted as dragging to right and vice versa.
Any suggestion? Or is there anyway in (1) to say CenterX="50%" ?

All you need to do is to set <uiElement RenderTransformOrigin="0.5,0.5"/>. Your scale transform will not need translation after that.

Related

How to flip a Path element horizontally

I have this <Path> element in a xaml file. I would like to create a copy and flip it horizontally so that the shape will point in the other direction. The <Path> has a really long Data field so I was wondering if there was a way to flip one of the elements instead of just eyeballing the element and manually making it appear the same shape and size.
I looked into flipping the image programatically using RenderTransform and ScaleTransform, but I am afraid it might hinder the performance of the application especially during a window resize.
References: https://learn.microsoft.com/en-us/dotnet/framework/wpf/graphics-multimedia/transforms-overview
Is there a protocol or way I can translate the Path element's Data
field into its horizontally flipped opposite in a way that wonder hurt
the performance of the application?
If you want to mirror the shape you might want to try this:
<Path data= "...">
<Path.RenderTransform>
<ScaleTransform ScaleX="-1.0"/>
</Path.RenderTransform>
</Path>
This doesn't really hurt the performance, since all rendered elements are transformed at some point anyway.

How to draw shape element faster and make them scale in wpf?

I have this problem.
So I have a bunch of data that must be visualized on a canvas (say more than 5000 items). So I draw them as a bunch of vertical rectangles over a horizontal line, some thing like this:
---|--|||||---|---|||---||----|||||||--------
Now, because the canvas is small, I only draw a different amount of rectangles at different zoom level. So if I zoom in more, the line get longer, and more rectangles I can see.
Problem is every time I zoom in, I have to clear the whole canvas, and redaw everything with the new zoom scale. And it is really suck, the drawing is slow and scaling not really nice.
So I wondering is there a way I can achieve a faster drawing, and good zooming (like those vector graph, you can zoom in unlimited)??
Have you tried ScaleTransform Class?
<Canvas.RenderTransform>
<ScaleTransform ScaleX="2" ScaleY="2" />
</Canvas.RenderTransform>
See How to: Scale an Element too. For performance reasons:
Freeze your Freezables.
Update Rather than Replace a RenderTransform
You may be able to update a Transform rather than replacing it as the
value of a RenderTransform property. This is particularly true in
scenarios that involve animation. By updating an existing Transform,
you avoid initiating an unnecessary layout calculation.
Have you looked at the ZoomableCanvas? I haven't used it, but it looks like it's designed to do exactly what you want.

How do I create a vertical text block without using an ItemsControl?

Alright, trying this again. All I want is to rotate a text block, nothing tricky. And I don't want to do it using an ItemsControl because it will require using a control for each and every letter, which is way too expensive for my needs.
Despite the controversy if it's a duplicate or not, there may be a way to achieve vertical text on a very low level, involving a GlyphRun. I haven't tested that in detail, but what i know is, you would have to
create a GlyphRun with the IsSideways property set to true, meaning
all character will be rotated 90° counter-clockwise,
get a DrawingContext and push (via PushTransform) a 90° clockwise RotateTransform onto it,
draw the GlyphRun to the DrawingContext.
A simple way to get an appropriate DrawingContext would be to override UIElement.OnRender.
Note: GlyphRun's constructor has 13 arguments, but the last 6 may be null :-)
<TextBlock Width="7" HorizontalAlignment="Left">
S<LineBreak/>
t<LineBreak/>
a<LineBreak/>
c<LineBreak/>
k
</TextBlock>

Strategy for implementing a complex curve editor with XAML/WPF

I want to implement a rather complex CurveEditor that has to support the usual requirements like:
freely scalable and moveable axis
different interpolation types per curve point (Linear, Cubic, Spline)
Tangents (joined and broken)
Selecting one or several points to edit (move, scale, delete) via Fence or Click
Only show handles and highlights for selected curve points
I don't want to manipulate actual WPF curves but an existing model with key/value/tangents sets and sample the precise shape of the curve from our implementation.
I already gathered some experience on implementing custom UserControls and Templates. But I want to make sure, I don't miss any apparent solution. I planned to have this general XAML-tree:
CurveEditor - Window holding all content
MainThumb : Enable dragging and scaling the editor range
XAxis : UserControl rending some scale on the left side
YAxis : UserControl rending some scale on the bottom
Curves : Canvas holding the curves
Curve : UserControl for a single curve
CurveName - Label of the curve
CurveLine - DrawingVisual that will render the actual curve by sampling the internal implementation of the spline function.
CurveEditPoints - Canvas that holds all edit points
CurveEditPoint - UserControl for a single edit point
LeftTangent - UserControl for the left tangent handle
LeftTangentThumb - For modifying the handle
RightTangent - UserControl for the right tangent handle
RightTangentThumb - For modifying the handle
CurvePointCenter - Visualisation of the actual point, select state and interpolation type.
CurvePointThumb - Thumb to select and drag point around
I know, this is quite a complex question and I am not asking for an actual implementation. I am interested in the following questions:
Can you recommend any tutorials or books that might help me (I already got Illustrated WPF, WPF Control Development Unleashed, and a couple of other)
Should minor elements like the Tangents be individual UserControls?
What container is best suited for hosting the individual "Curves", "EditPoints" and "Tangents". Right now, I use Canvas and Canvas.SetLeft/SetTop to position the children, but that feels "strange".
Should I use "Shapes" like Path or DrawingVisual-Classes to implement actual representation. Path is straight forward, but I am concerned about performance with hundreds of CurvePoints.
Should I use Transforms to rotate the tangents or is just fine to do some triangulation math in the code behind files?
Does the structure roughly make sense, or do you suggest a completely different approach?
you seem to have the right tools at hand, WPF Unleashed is excellent, but I guess you have that one already.
make individual UserControls in one of these cases:
you are using the same xaml all over the place (DRY)
you xaml file gets too big (get some components out)
you need to inherit from some class
this depends on how much codebehind you want.
you can, as you suggested in your comment, use an ItemsControl as a container for wherever you need selection between multiple items. so this could also be done on the level of Curves, not just on the level of points on the curve. Depending on how you want to handle drawing of the actual lines and curves you can even have an ItemsControl for those. (on a side note: you will not have virtualization out of the box though, as your items won't have a constant height)
Path is OK with hundreds of CurvePoints. If you have 10.000, I'd say you could get problems.
can't imagine how a transform should be used here, maybe inside an Adorner.
your structure looks good. you will be able to implement all of this. I will suggest though how I would do it:
first of all use MVVM.
CurveEditor
ListBox(Panel=Canvas)(ItemsSource=Curves)(ItemTemplate=CurveControl)
CurveControl
Canvas(Background=Transparent) <= I'm not sure if standard is white, but you don't want to overlap other Curves...
CurveName
ListBox(Panel=Canvas(Background=Transparent))(ItemsSource=CurveParts)
ListBox(Panel=Canvas(Background=Transparent))(ItemsSource=CurvePoints)(ItemTemplate=>EditPointControl)
EditPointControl
Canvas
Thumb(Template = Ellipse) (Name=CenterHandle) (with some Visualstates for Selection and hiding of Tangents)
Thumb(Template = Ellipse) (Name=LeftHandle)
Thumb(Template = Ellipse) (Name=RightHandle)
Line (Binding X/Y to Centerpoint and LeftHandlePoint)
Line (Binding X/Y to Centerpoint and RightHandlePoint)
I have stated to set ItemTemplate for the ListBox. You can however style the listbox however you want (I think the standard style includes a border, you might want to remove that or set bordersize=0) and set instead of ItemTemplate the ItemContainerStyle and bind to IsSelected so you have control over IsSelected from your ViewModel (look here for what I mean).
So the viewmodel looks like this:
- CurveEditorViewModel
- ObservableCollection<CurveViewModel> Curves
- CurveViewModel
- string Label
- (Point LabelPlacement)
- bool IsSelected
- ObservableCollection<CurvePointViewModel> CurvePoints
- ObservableCollection<CurvePartViewModel> CurveParts
- CurvePointViewModel
- Point Position
- bool IsSelected
- Point LeftHandle
- Point RightHandle
- CurvePartViewModel
- CurvePointViewModel StartPoint
- CurvePointViewModel EndPoint
- Path CurvePath
in here you can subscribe to CurvePointViewModel's PropertyChanged and recalculate the Path you're exposing.
I'd probably improve on it as I go but that'd be my first guess.
There are some details you might want to watch out for. eg: the style for the thumbs might be a visible circle in the middle and an invisible bigger one around that with background=transparent. that way you can have your visible circle small, but have the user use the tumb in an area around the small circle.
EDIT:
here is an Example for the Thumb:
<Thumb Width="8" Height="8" Cursor="Hand" Margin="-4">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Grid>
<Ellipse Fill="Transparent" Margin="-6"/>
<Ellipse Stroke="Red" StrokeThickness="2"/>
</Grid>
</ControlTemplate>
</Thumb.Template>
</Thumb>
as you want to position this at a specific point on a canvas setting the Margin to minus half the width and height will place the center of the circle on that point. Furthermore, having that inner ellipse with a transparent fill and Margin of -6 you will get a 6px bigger radius around the inner (smaller) circle where you can drag the thumb.

Move Canvas In Reverse Direction

I have two canvases.
Currently, when I drag a rectangle inside of the first canvas, it also moves the rectangle in the second canvas. I do this using TranslateTransform.
What I want to do is when I drag rectangle (A) to the left, rectangle (B) moves to the right, and vice versa etc.
Is there a relatively easy way to do this?
Chris
Would you be able to post some code as what you have already implemented if anything?
To do this I would simply apply an event to when the first rectangle moves (or is translated) to pass the transformation information to a method that translates the second rectangle with a negative value of x to make a "Reverse" transformation.
Easiest way would probably be to create a Converter which converts a value to its opposite (so positive to negative and vise versa). Apply it to the RenderTransform and bind it to the other Canvas TranslateTransform x/y values.
make it inside a double animation tag
<DoubleAnimation AutoReverse="True" />

Resources