Pages

Showing posts with label my projects. Show all posts
Showing posts with label my projects. Show all posts

Wednesday, October 22, 2014

The Simplest WPF Diagram Designer - Part 3

2 weeks ago I started a series of tips about WPF Diagram Designer (part1, part2). But as you know, there is nothing new under the sun. I have been pointed that there were few similar articles already posted on CodeProject so I`ve decided to post my next part of work here. I will add basic keyboard binding and RavenDB/XML save-load functionality. The source code can be found here: https://bitbucket.org/JleruOHeP/mywpfdesigner/src.

Keyboard commands
I have added 2 commands: Delete the current element and edit the text of the current element.
For the sake of simplicity I have changed the meaning of the Tag property for shapes. Now it stores the shape entity itself instead of just the Id. Because of that it became much faster to work with them. Because user can`t select the line we need to delete the connector, line and the opposite connector when someone selects the connector and presses Del. Now the Connector should know not only its host but as well its line. Ok. And the ChangeText command is really simple - as we already have all needed functionality.

RavenDB
I wanted to pick some embedded NoSQL database and the RavenDB was an obvious choice. I added wrapper class for that matter with a static EmbeddableDocumentStore DocumentStore and 2 methods - to Save the whole model or to load all objects of a specific type. With that implementation there is nothing complex about saving and for loading you have to clear the Canvas, reinitialize lines (because they do not store their coordinates - only connectors; connectors should be reconnected to their hosts), redraw the shapes, and finally recreate the Model class (assign proper commands and set it as a DataContext for a Window).

Also as the connectors are not used as a separate entity - I removed them from the model class. Now there are only 2 collections - for lines and shapes.

XML Serialization
It is really simple. Our Model class already has everything it needs - so we can easily use the XmlSerializer class.

 var serializer = new XmlSerializer(typeof(MyCanvasModel));
 using (var writer = new StreamWriter("data.xml"))
 {
  serializer.Serialize(writer, Model);
  writer.Close();
 }

The only thing we need to add - is [XmlIgnore] attribute for all the commands because they cant be serialized.

Thursday, July 31, 2014

Elliptic context menu in WPF

Today I've decided to try build a simple elliptic context menu, something like in games. While you holding right mouse button you can pick something. As it is just a prototype I will build the simplest drawing application. With that menu user would be able to select a background color.

So, first thing first. Basic layout: just a canvas with a predefined background color and 2 events for right mouse up and down. OnDown should create context menu elements and OnUp should destroy them. And those elements should be created around mouse cursor.
The easiest way to create that circular shape is to use Path with ArcSegment. And the only trick here is trigonometry. We need to provide start and end points for the arc and they should be on a circle. Basically, x = cos and y = sin. Plus we should calculate the correct angle - in radians. Thats the all mathematics we will need!

Here is my method to create a menu segment:
private static Path CreateEllipticMenu(Point center, Brush color, int currentNumber, int maxNumber)
{
    var menu = new MyMenu {MyBrush = color};
    const int size = 50;
    var angleStart = currentNumber*2*Math.PI/maxNumber;
    var angleEnd = (currentNumber + 1)*2*Math.PI/maxNumber;

    var startX = center.X + size * Math.Cos(angleStart);
    var startY = center.Y + size * Math.Sin(angleStart);

    var endX = center.X + size * Math.Cos(angleEnd);
    var endY = center.Y + size * Math.Sin(angleEnd);

    var myPath = new Path();
    myPath.Stroke = menu.MyBrush;
    myPath.StrokeThickness = 20;
    myPath.HorizontalAlignment = HorizontalAlignment.Left;
    myPath.VerticalAlignment = VerticalAlignment.Center;
    var arc = new ArcSegment();
    arc.IsLargeArc = false;
    arc.Size = new Size(size, size);
    arc.SweepDirection = SweepDirection.Clockwise;
    arc.Point = new Point(endX, endY);
    var pathFigure = new PathFigure();
    pathFigure.StartPoint = new Point(startX, startY);
    pathFigure.Segments.Add(arc);
    myPath.Data = new PathGeometry(new List<PathFigure> {pathFigure});

    myPath.MouseEnter += (e, s) => { myPath.Stroke = Brushes.Red; menu.IsSelected = true; };
    myPath.MouseLeave += (e, s) => { myPath.Stroke = menu.MyBrush; menu.IsSelected = false; };

    myPath.Tag = menu;
    return myPath;
}

I have also defined mouse enter and mouse leave events so I can select active menu item and every menu item has MyMenu object associated with it. That class is just a helper:
public class MyMenu
{
    public Brush MyBrush { get; set; }
    public bool IsSelected { get; set; }
}

Well, thats all! Just as an addition here is an example of usage:

private void MyCanvas_OnMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    var center = new Point(e.GetPosition(MyCanvas).X, e.GetPosition(MyCanvas).Y);

    MyCanvas.Children.Add(CreateEllipticMenu(center, Brushes.MediumSlateBlue, 0, 4));
    MyCanvas.Children.Add(CreateEllipticMenu(center, Brushes.MediumAquamarine, 1, 4));
    MyCanvas.Children.Add(CreateEllipticMenu(center, Brushes.MediumVioletRed, 2, 4));
    MyCanvas.Children.Add(CreateEllipticMenu(center, Brushes.LightYellow, 3, 4));
}

private void MyCanvas_OnMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
    int i = 0;
    while (i < MyCanvas.Children.Count)
    {
        var child = MyCanvas.Children[i];
        if (child is Path && (child as Path).Tag is MyMenu)
        {
            var menu = (child as Path).Tag as MyMenu;
            if (menu.IsSelected) MyCanvas.Background = menu.MyBrush;

            MyCanvas.Children.Remove(child as Path);
            continue;
        }
        i++;
    }
}

Monday, March 3, 2014

Service runner

One of my recent tasks was to create a "service runner" - a small application that we can use to more easily test our service projects. That app was relatively simple yet useful so I`ve decided that it is worth posting on Git! (Yep, my very first repository on Git)

It is available here: ServiceRunner. And you can even see my photo there! :)

But speaking of that tool. As I`ve said it is quite simple - it is just a WinForms application with one referenced "FakeService". FakeService is there only for demonstration purposes. In order to use that you will have to reference your service project(s) to it, add a wrapper in the FormLoad event - in order to be able to choose from a dropdown and set breakpoints!

This helper will call OnStart and OnStop methods using corresponding buttons. In addition this app will try to load corresponding App.Config file, so your services might use that as you wish - using custom sections etc.

And I would like to announce some features I want to add in future.

  1. Logging. For now it is writing only Start|Stop events and it would be great to catch all the logging from the given service - somehow
  2. Dynamic service loader. It might be easier to use by only choosing the right path for the corresponding dll and app.config file.
  3. I`m not sure but other events like OnShutdown might be usefull for someone as well...

Monday, January 27, 2014

DailyHobby.tk

Last week I was busy making a new website. My wife had the idea of creating a website dedicated to selecting the hobby for every evening. When you do have a free evening or day and don`t know what to do - try visiting that site and picking anything you want. And of course I'm open to constructive criticism :)

This site is quite simple and to illustrate this let me show the make log. I`ve been spending my spare time after work every day - it was like 1-2 hours every day.
Day 1: Discussion of the idea and choosing hosting;
Day 2: Two paged  book-like view... Failed :)
Day 3: Added database access and deployed that database to the hosting;
Day 4: Added one paged book-like view and dynamic loading of the content;
Day 5: Added stylysh navigation menu and alternative page change;
Day 6: I was lazy ^_^
Day 7: Added static pages and updated a live database with actual content.

And that`s all!

Take a look at this site: dailyhobby.tk

Thursday, January 2, 2014

New blog

I`ve decided to start a new blog. The new one will be about my idea to create games as that always was very exciting for me. Maybe I don`t have enough experience or there is only me and no one can support me with music, for example, but let`s see what it will become in about a year!
I hope that my hobby will turn into a serious business :)

So, I`m going to describe my progress and ideas there - http://jlergames.blogspot.com.au/, post complete code example somewhere as an open source project (most likely on the codeplex) and interesting algorithms (at least interesting for me) here.

Lets do it!