Search code examples
c#livecharts

Shift key simplification


I am currently working on a project, which deals with charts from Livecharts and I have been trying the last days to implement the Shift + mouse selection of points (the way it works for file explorer, including the combination with Ctrl key), but my code seems to look very complicated for only that function and I want to make it easier. Nevertheless I have not found a way to make it, more undestandable. The code is the following:

private int movingPointIdx = -1; //-1: no point moving
List<int> highlightedIndex = new List<int>();
private int lastClickedPointIdx = -1;
int firstvaluepoint = 0;

private void ChartOnDataClick(object sender, ChartPoint p)
{
    Chartvalues = (ChartValues<ObservablePoint>)SeriesCollection[0].Values;
    bool shiftclick = false;
    int firstselectedpoint = 0;

    foreach (ObservablePoint val in Chartvalues)
    {
        if (val.X == p.X && val.Y == p.Y) //this is the clicked point
        {
            movingPointIdx = Chartvalues.IndexOf(val); //get index of currently clicked point
            firstselectedpoint = movingPointIdx;

            Chartvalues[movingPointIdx].X = Chartvalues[movingPointIdx].X; //highlights selected point

            if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) //Ctrl
            {
                if (highlightedIndex.Contains(movingPointIdx)) //remove point if already is in the highlightedIndex list
                {
                    highlightedIndex.Remove(movingPointIdx);
                    firstselectedpoint = movingPointIdx;
                    shiftclick = false;
                    return;
                }
                else //otherwise add it to the highlightedIndex list
                {
                    highlightedIndex.Add(movingPointIdx);
                    highlightedIndex.Sort();
                    firstselectedpoint = movingPointIdx;
                    shiftclick = false;
                }
            }
            else if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) //Shift
            {
                if (!shiftclick)
                {
                    highlightedIndex.Clear();
                    shiftclick = true;
                }

                if (lastClickedPointIdx > -1) //highlights all points 
                {                            
                    if (firstvaluepoint > firstselectedpoint)
                    {
                        for (int i = firstselectedpoint; i <= firstvaluepoint; i++)
                        {
                            highlightedIndex.Add(i);
                        }
                    }
                    else
                    {
                        for (int i = firstvaluepoint; i <= firstselectedpoint; i++)
                        {
                           highlightedIndex.Add(i);
                        }
                    }                                                        
                }
            }
            else //no modifier key pressed -> only add the current point to the list
            {
                highlightedIndex.Clear();
                highlightedIndex.Add(movingPointIdx);
            }

            lastClickedPointIdx = movingPointIdx;
            if (!shiftclick)
                firstvaluepoint = firstselectedpoint;                    
        }
    }
}

Solution

  • The first step there is a way to convert that if logic:

    if (val.X == p.X && val.Y == p.Y) //this is the clicked point
    

    If you do inversion it would be a lot cleaner for read

    if(!(val.X == p.X && val.Y == p.Y)){
    continue;
    }
    

    You can easly change that condition to a function

    private bool IsTheClickedPoint(ObservablePoint val, ChartPoint p){
        return val.X == p.X && val.Y == p.Y;
    }
    

    So that if would be like this:

    if(!IsTheClickedPoint(val,p)){
    continue;
    }
    

    The second step is to make decision handling for that if's when you want to know if some key is clicked. What would you do if you need to implement ex. alt click? It will be the next ifology?

    public bool IsCtrlClicked(){
    return Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl);
    }
    

    So the last and third step I would recommend you move it to something like a command pattern to make decisions easier. Here is a graph for Java but it looks nice and easy:

    CommandPatternClassDiagram