/* ElementPickerViewModel.cs * part of zaaReloaded2 * * Copyright 2015-2017 Daniel Kraus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using Bovender.Mvvm; using Bovender.Mvvm.Messaging; using Bovender.Mvvm.ViewModels; using System.Collections.ObjectModel; using zaaReloaded2.Controller.Elements; namespace zaaReloaded2.ViewModels { /// /// View model that presents a list of zaaReloaded2.Contorller.Elements.ElementBase /// classes to choose from. Depending on which constructor is used, this view model /// presents either a list of ControlElementBase-derived classes, a list of /// FormatElementBase-derived classes, or both. /// class ElementPickerViewModel : ViewModelBase { #region Properties /// /// A two-dimensional tree /// public IList Categories { get; private set; } /// /// Gets the currently selected element, or null if no element is selected. /// /// /// TODO: Raise PropertyChanged event. /// public ElementViewModel Selected { get; private set; } #endregion #region Commands public DelegatingCommand ChooseElementCommand { get { if (_chooseElementCommand == null) { _chooseElementCommand = new DelegatingCommand( param => DoChooseElement(), param => CanChooseElement()); } return _chooseElementCommand; } } #endregion #region Messages /// /// A message that is sent out when an element has been chosen; /// the message content is the element's view model with the element /// wrapped inside. /// public Message ElementChosenMessage { get { if (_elementChosenMessage == null) { _elementChosenMessage = new Message(); } return _elementChosenMessage; } } #endregion #region Constructors public ElementPickerViewModel(bool allowControlElements) { Categories = new List(); if (allowControlElements) { AddCategory( new CategoryViewModel( Properties.Settings.Default.ControlElementLabel, new Collection() { CreateControlElementViewModel(new SelectFirstDay()), CreateControlElementViewModel(new SelectLastDay()), CreateControlElementViewModel(new SelectEachDay()), CreateControlElementViewModel(new TwoColumns()), CreateControlElementViewModel(new NextColumn()), } ) ); } CreateFormatElementViewModels(); } /// /// Creates a new element picker for control elements only; /// the selected ControlElementVieModel will copy the Elements /// property from a source view model. /// /// ControlElementViewModel /// whose Elements property to copy. public ElementPickerViewModel(ControlElementViewModel copyFromViewModel) { Categories = new List(); AddCategory( new CategoryViewModel( Properties.Settings.Default.ControlElementLabel, new Collection() { CreateControlElementViewModel(new SelectFirstDay(), copyFromViewModel), CreateControlElementViewModel(new SelectLastDay(), copyFromViewModel), CreateControlElementViewModel(new SelectEachDay(), copyFromViewModel), CreateControlElementViewModel(new TwoColumns()), CreateControlElementViewModel(new NextColumn()), } ) ); } #endregion #region Private methods void CreateFormatElementViewModels() { AddCategory( new CategoryViewModel( Properties.Settings.Default.FormatElementLabel, new Collection() { CreateFormatElementViewModel(new Items()), CreateFormatElementViewModel(new CustomText()), } ) ); } void AddCategory(CategoryViewModel category) { category.PropertyChanged += ElementViewModel_PropertyChanged; Categories.Add(category); } /// /// Creates a new ControlElementViewModel that wraps a ControlElementBase /// object. The display string of the ControlElementViewModel is taken /// from the canonical Label of the control element. /// ViewModelBase CreateControlElementViewModel(ControlElementBase element) { ControlElementViewModel vm = new ControlElementViewModel(element); vm.DisplayString = element.Label; vm.PropertyChanged += ElementViewModel_PropertyChanged; return vm; } ViewModelBase CreateControlElementViewModel( ControlElementBase element, ControlElementViewModel copyFromViewModel) { ControlElementViewModel vm = new ControlElementViewModel(element, copyFromViewModel); vm.DisplayString = element.Label; vm.PropertyChanged += ElementViewModel_PropertyChanged; return vm; } /// /// Creates a new FormatElementViewModel that wraps a FormatElementBase /// object and has a custom display string. The custom display string /// is necessary because format elements do not have a canonical label. /// ViewModelBase CreateFormatElementViewModel(FormatElementBase element) { FormatElementViewModel vm = new FormatElementViewModel(element); vm.PropertyChanged += ElementViewModel_PropertyChanged; return vm; } void ElementViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { // Casting sender as ElementViewModel may result in Null, but this // is a desired effect because category headings may be selected // in a view, but are not valid ElementViewModels that we could // 'choose'. In addition, when an element is selected, another one // is deselected, and the event triggers twice, once for the selected // element and once for the deselected one. ElementViewModel elementVM = sender as ElementViewModel; if (elementVM != null && elementVM.IsSelected && e.PropertyName == "IsSelected") { Selected = elementVM; } } void DoChooseElement() { if (CanChooseElement()) { ElementChosenMessage.Send(new ViewModelMessageContent(Selected)); DoCloseView(); } } bool CanChooseElement() { return Selected != null && Selected.IsSelected == true; } #endregion #region Implementation ov ViewModelBase public override object RevealModelObject() { throw new NotImplementedException(); } #endregion #region Fields DelegatingCommand _chooseElementCommand; Message _elementChosenMessage; #endregion } }