Pages

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++;
    }
}

Tuesday, July 29, 2014

FTDI device monitor

As usual I want to describe one of the last things I've done. Yeah I have not written anything to the blog for a while but thats not because I have not done anything but because I am planing something new!

Still, for now I want to describe how to get the list of connected USB devices using FTDI drivers. It is quite easy. Everything is done through the FTDI class.
First of all - you can check the number of connected devices with a call:

var monitor = new FTDI();
UInt32 newDeviceCount = 0;
var status = monitor.GetNumberOfDevices(ref newDeviceCount);
if (status != FTDI.FT_STATUS.FT_OK) //something wrong!

The last check is there just for exceptions. Then you can get the actual list of connected devices. As this library follows c++ style - you have to pass an initialized array of FT_DEVICE_INFO_NODE:

var ftdiDeviceList = new FTDI.FT_DEVICE_INFO_NODE[newDeviceCount];
ftStatus = newDevice.GetDeviceList(ftdiDeviceList);
if (ftStatus != FTDI.FT_STATUS.FT_OK) //something wrong!

And finally we can iterate through devices and get some information about them:

for (var i = 0; i < newDeviceCount; i++)
{
    _devices.Add(new DeviceDTO(i, //_devices here is a List of a simple DTO class
    ftdiDeviceList[i].Flags,
    ftdiDeviceList[i].Type,
    ftdiDeviceList[i].ID,
    ftdiDeviceList[i].LocId,
    ftdiDeviceList[i].SerialNumber,
    ftdiDeviceList[i].Description));
}

And thats all! As a side node - for my app I had to implement this as a infinite loop - watching for a new connections. It was something like this:

 var deviceFinder = new BackgroundWorker();
 deviceFinder.DoWork += (ev, sn) =>
 {
    UInt32 prevDeviceCount = 0;
    var monitor = new FTDI();

    while (true)
    {
        UInt32 newDeviceCount = 0;
        var status = monitor.GetNumberOfDevices(ref newDeviceCount);
        if (status != FTDI.FT_STATUS.FT_OK) continue;

        var dDevice = newDeviceCount - prevDeviceCount;
        if (dDevice != 0)
        {
            UpdateList(); //updates that _devices List
        }

        prevDeviceCount = newDeviceCount;

        Thread.Sleep(5000);
    }
};
deviceFinder.RunWorkerAsync();

Wednesday, March 19, 2014

Website design

One of the most popular sites is google - 1 picture, 1 textbox and 2 buttons. One of those two is never used...

So why the hell they are continue to make those flashy websites with self-advertisments? Probably it is because of designers that came from the street world. The shops have to make a flashy showcase because customers see it in a first place and based on it make a choice - which shop to visit. But with websites it is completely different. The user have already typed your url. Or asked google for direction (and in google search results they are all the same!).
It is much better to make a good user experience design - design where it is completely clear where to read what you want and where to put your credit card number! I`m not sure, but if some site is too provoking, personally, I would try not to use it again...
Moreover, most of experienced users made a habit to ignore all the flashy stuff on the right, left and top of the page. So why to put your actual content into self-sliding panel? It just annoying!

Well what I want to say is - lets make a great user-friendly websites! :)

And a little picture related to this issue:

Tuesday, March 18, 2014

Google Custom Search and Firefox

Another thing I`ve worked on was an implementing of the google custom search for our website. We`ve decided to use two paged view. The script for search input was stored into a user control whichwas used on every page and the script for results was added to a separate page.

Clean and easy! Almost... This worked just fine for most of the browsers - Chrome (obviously), Opera, Safari... But the Firefox was an unpleasant exception. It was throwing google.search.Search.apiaryXXXXX is not a function, like:

TypeError: google.search.Search.apiary17868 is not a function

So this task will require something bigger then a copy-paste :)
And the answer was to implement our own control for search input, because the exception comes from 2 google scripts on a single page..  Moreover - implementing input string as a separate control will result in more flexible design!

The simplest implementation in WebForms - 1 TextBox, 1 Button and a handler for that button with redirect:

Response.Redirect(_searchResultsUrl + "?" + QuerystringParam + txt.Text);



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...

Friday, February 14, 2014

My approach to learn things

I was always eager to learn new things. First of all - it is just fun to know things! And from a developers perspective learning new stuff enlarges your horizons...

Recently I've accidently stumbled on that question at the programmers.stackexchange. I thought about adding my answer-opinion there but then realized that it can take a while (I mean phrasing of it). So I've decided to add a blog post about my approach :)

As a developer you have to learn new tricks almost every day. Every task means that you have to solve a problem, if that problem is not trivial then there is more than one possible solutions. Every of those solutions are better than others :)

But getting back to the question about learning things. Right now I am learning MongoDB + Python with a MongoDB courses and a Unity3d by myself. Both of those thing are completely optional for me, I just want to know more. Maybe I will use them later...

Interesting part about this is that I am learning them differently. For mongoDB I am watching online courses and for Unity I am playing all by myself. Probably, first approach is a bit more optimal because it was created by professionals; it is much easier to follow their way then reinventing the bicycle!

But for me the main part of the education is an independent study! Even with those courses I am trying to finish my homework before watching corresponding lessons. Just to make sure that I am able to do such things :) Reading documentation and searching for answers are the main skills of a professional. Yes, the true professional knows a lot, but no one can know everything!

So, overall, watching tutorials are ok to get an general impression about something or to find a solution for a specific task. But I would use them only occasionally. Because for now I am able to try solving problems with my existing experience. This, however, does not mean that I am against tutorials. I am using them as well. my schema is following: try something by myself and only then check the internet. I am checking external sources in both situations when i have successfully solved something or stuck.

For me especially nice to find out that I`ve done something the same way as a recognized professional or even better :)

To sum all up.
If it is something completely new for me, then I will try to find a "general-impression" tutorial;
If I've worked with a given technology or it's stack then I will try to do something by myself and only after it will check the external sources. If they are better then my result I am happy to learn from them!

Saturday, February 1, 2014

SignalR and MVC4

I had to use SignalR this week and it was quite funny experience :) And, fortunately, successful!

The main problem I`ve faced was about different versions of the SignalR and MVC. If you would try to install SignalR package with windowed NuGet interface you will find that it can install the latest version - 2.0.2. But the installation will fail, because it uses the latest version of OWIN.Security, which requires .Net 4.5...

So the solution is to use NuGet console! Use
install-package Microsoft.AspNet.SignalR -Version 1.1.3
and it will install everything! Then, as always create a new hub class, register it and add signalr.js and signalr/hubs scripts. (as in tutorial).

But for me it was little harder :) I`ve tried to add SignalR 2.0 and failed, but it have not rolled back correctly. The javascript files were left in Scripts folder... And when I`ve reinstalled the correct version they were not downgraded!

Because of that I was not able to connect to hub - my overridden OnConnect just was not called! I had to make parallel project and install everything in there in a right way to connect...

Hope this notes will help someone :)