<commit_before>﻿module TodoList

open Defs
open FsXaml
open System.Reactive.Linq
open System.Reactive.Subjects
open System.Windows
open System.Collections.ObjectModel
open System.Collections.Specialized
open System.Windows.Controls
open System.Windows.Media
open System

type FilteringType = All | Active | Completed
type TodoListEvents = 
    | Add
    | Delete of ItemModel
    | Checked of bool * ItemModel
    | CheckAll
    | UncheckAll
    | NewItemTextChanged of string
    | FilteringChanged of FilteringType
    | SelectionChanged of ItemModel option

and ItemModel(text : string, _done : bool) = 
    member val Text = Defs.Prop text
    member val Done = Defs.Prop _done

module Item = 
    type Control = XAML< "TodoItem.xaml", true >
    
    type View(m : ItemModel) as this = 
        inherit Defs.View<TodoListEvents, Control, ItemModel>(Control(), m)

        do
          let v = (this.Root)
          Observable.merge (v.MouseEnter --> Visibility.Visible) (v.MouseLeave --> Visibility.Collapsed)
          |>  Observable.add (fun vis -> v.buttonDelete.Visibility <- vis)
          
        
        override x.EventStreams = 
            [ x.Root.buttonDelete.Click --> Delete x.Model
              x.Root.checkDone.Unchecked --> Checked(false, x.Model)
              x.Root.checkDone.Checked --> Checked(true, x.Model) ]
        
        override x.SetBindings(m : ItemModel) = 
            m.Text |> Observable.add(fun t -> x.Root.labelText.Content <- t)
            m.Done |> Observable.add(fun d -> x.Root.checkDone.IsChecked <- System.Nullable d;
                                              x.Root.labelText.Foreground <- if d then Brushes.Gray else Brushes.Black)

type TodoListModel() = 
    let items = new ObservableCollection<ItemModel>()
    let collChanged = items.CollectionChanged |> Observable.filter Defs.isAddOrRemove
    
    let totalCount = 
        collChanged
        |> Observable.map (fun _ -> items.Count)
        |> Observable.toProperty 0
    
    let doneCount = 
        collChanged
        |> Observable.choose Defs.toAddOrRemove
        |> Observable.map (fun _ -> 
               items
               |> Seq.filter (fun i -> i.Done.Value)
               |> Seq.length)
        //                    |> Observable.scan (fun prev change -> prev) 0
        |> Observable.toProperty 0
    
    member x.Items : ObservableCollection<ItemModel> = items
    member x.TotalCount : ReactiveProperty<int> = totalCount
    member x.DoneCount : ReactiveProperty<int> = doneCount
    member val NewItemText : ReactiveProperty<string> = Prop("")
    member val FilteringType : ReactiveProperty<FilteringType> = Prop(All)
    member val SelectedItem : ReactiveProperty<ItemModel option> = Prop(None)


type TodoListWindow = XAML< "TodoList.xaml", true >
type TodoListView(mw : TodoListWindow, m) = 
    inherit DerivedCollectionSourceView.T<TodoListEvents, Window, TodoListModel>(mw.Root, m)

    let filter (m:TodoListModel) (x:Item.View) =
        match m.FilteringType.Value with
        | All -> true
        | Completed -> x.Model.Done.Value
        | Active -> not x.Model.Done.Value

    member val ItemsCollectionView:ComponentModel.ICollectionView = null with get,set

    override this.EventStreams = 
        [ // (un)check all
          mw.buttonCheckAll.Click --> CheckAll
          mw.buttonUncheckAll.Click --> UncheckAll
          // filtering
          mw.radioFilterAll.Checked --> FilteringChanged All
          mw.radioFilterActive.Checked --> FilteringChanged Active
          mw.radioFilterCompleted.Checked --> FilteringChanged Completed
          // on Enter keypress, create an item
          mw.tbNewItem.KeyDown
          |> Observable.filter (fun e -> e.Key = System.Windows.Input.Key.Enter)
          |> Observable.mapTo Add
          // new item's text
          Observable.Throttle(mw.tbNewItem.TextChanged, TimeSpan.FromMilliseconds 100.0)
          |> DispatcherObservable.ObserveOnDispatcher
          |> Observable.map (fun _ -> NewItemTextChanged mw.tbNewItem.Text)
          mw.list.SelectionChanged |> Observable.map (fun _ ->
            SelectionChanged (if mw.list.SelectedItem <> null then (Some (mw.list.SelectedItem :?> Item.View).Model) else None)) ]<commit_msg>experimenting with RX Drag and drop<commit_after>﻿module TodoList

open Defs
open FsXaml
open System.Reactive.Linq
open System.Reactive.Subjects
open System.Windows
open System.Collections.ObjectModel
open System.Collections.Specialized
open System.Windows.Controls
open System.Windows.Media
open System

type FilteringType = All | Active | Completed
type TodoListEvents = 
    | Add
    | Delete of ItemModel
    | Checked of bool * ItemModel
    | CheckAll
    | UncheckAll
    | NewItemTextChanged of string
    | FilteringChanged of FilteringType
    | SelectionChanged of ItemModel option

and ItemModel(text : string, _done : bool) = 
    member val Text = Defs.Prop text
    member val Done = Defs.Prop _done

module Item = 
    type Control = XAML< "TodoItem.xaml", true >
    
    type View(m : ItemModel) as this = 
        inherit Defs.View<TodoListEvents, Control, ItemModel>(Control(), m)

        do
          let v = (this.Root)
          Observable.merge (v.MouseEnter --> Visibility.Visible) (v.MouseLeave --> Visibility.Collapsed)
          |>  Observable.add (fun vis -> v.buttonDelete.Visibility <- vis)
          
        
        override x.EventStreams = 
            [ x.Root.buttonDelete.Click --> Delete x.Model
              x.Root.checkDone.Unchecked --> Checked(false, x.Model)
              x.Root.checkDone.Checked --> Checked(true, x.Model) ]
        
        override x.SetBindings(m : ItemModel) = 
            m.Text |> Observable.add(fun t -> x.Root.labelText.Content <- t)
            m.Done |> Observable.add(fun d -> x.Root.checkDone.IsChecked <- System.Nullable d;
                                              x.Root.labelText.Foreground <- if d then Brushes.Gray else Brushes.Black)

type TodoListModel() = 
    let items = new ObservableCollection<ItemModel>()
    let collChanged = items.CollectionChanged |> Observable.filter Defs.isAddOrRemove
    
    let totalCount = 
        collChanged
        |> Observable.map (fun _ -> items.Count)
        |> Observable.toProperty 0
    
    let doneCount = 
        collChanged
        |> Observable.choose Defs.toAddOrRemove
        |> Observable.map (fun _ -> 
               items
               |> Seq.filter (fun i -> i.Done.Value)
               |> Seq.length)
        //                    |> Observable.scan (fun prev change -> prev) 0
        |> Observable.toProperty 0
    
    member x.Items : ObservableCollection<ItemModel> = items
    member x.TotalCount : ReactiveProperty<int> = totalCount
    member x.DoneCount : ReactiveProperty<int> = doneCount
    member val NewItemText : ReactiveProperty<string> = Prop("")
    member val FilteringType : ReactiveProperty<FilteringType> = Prop(All)
    member val SelectedItem : ReactiveProperty<ItemModel option> = Prop(None)


type TodoListWindow = XAML< "TodoList.xaml", true >
type TodoListView(mw : TodoListWindow, m) = 
    inherit DerivedCollectionSourceView.T<TodoListEvents, Window, TodoListModel>(mw.Root, m)

    let filter (m:TodoListModel) (x:Item.View) =
        match m.FilteringType.Value with
        | All -> true
        | Completed -> x.Model.Done.Value
        | Active -> not x.Model.Done.Value

    do
        mw.list.AllowDrop <- true
        let h = fun(x,y) -> ()
        let pos (e:Input.MouseEventArgs) = e.GetPosition(mw.list)
        let down = mw.list.PreviewMouseLeftButtonDown |> Observable.map pos
        let move = mw.list.MouseMove |> Observable.map pos
        let up = mw.list.PreviewMouseLeftButtonUp |> Observable.map pos
        let s= Observable.SelectMany (down, fun start ->
            let mm = Observable.TakeUntil((move.StartWith start), up)
            let mmz = mm.And(mm.Skip(1)).Then(fun a b -> b.X-a.X,b.Y-a.Y)
            Observable.When(mmz)
            )
        s.Add (tracefn "MOUSE %A")
//        let m = mw.list.MouseMove.StartWith down |> Observable.TakeUntil up
//        m.
        ()

    member val ItemsCollectionView:ComponentModel.ICollectionView = null with get,set

    override this.EventStreams = 
        [ // (un)check all
          mw.buttonCheckAll.Click --> CheckAll
          mw.buttonUncheckAll.Click --> UncheckAll
          // filtering
          mw.radioFilterAll.Checked --> FilteringChanged All
          mw.radioFilterActive.Checked --> FilteringChanged Active
          mw.radioFilterCompleted.Checked --> FilteringChanged Completed
          // on Enter keypress, create an item
          mw.tbNewItem.KeyDown
          |> Observable.filter (fun e -> e.Key = System.Windows.Input.Key.Enter)
          |> Observable.mapTo Add
          // new item's text
          Observable.Throttle(mw.tbNewItem.TextChanged, TimeSpan.FromMilliseconds 100.0)
          |> DispatcherObservable.ObserveOnDispatcher
          |> Observable.map (fun _ -> NewItemTextChanged mw.tbNewItem.Text)
          mw.list.SelectionChanged |> Observable.map (fun _ ->
            SelectionChanged (if mw.list.SelectedItem <> null then (Some (mw.list.SelectedItem :?> Item.View).Model) else None)) ]
{'fraction_non_alphanumeric': 0.10018392296873309, 'fraction_numerical': 0.0016228497241155468, 'mean_word_length': 2.3504893077201885, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 116, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3394292', 'n_tokens_mistral': 2728, 'n_tokens_neox': 2608, 'n_words': 629}