public MinimapFormViewModel(IReadOnlyApplicationModel model, Dispatcher dispatcher) { this.model = model; this.dispatcher = dispatcher; this.startPositions = CreateStartPositionsArray(); // set up basic properties as observables var minimapVisible = model.PropertyAsObservable(x => x.MinimapVisible, nameof(model.MinimapVisible)); var map = model.PropertyAsObservable(x => x.Map, nameof(model.Map)); var minimap = map.Select(x => x.Match( y => y.PropertyAsObservable(z => z.Minimap, nameof(y.Minimap)), () => Observable.Return <Bitmap>(null))) .Switch(); // set up observables for property change notifications var mapChanged = model.PropertyChangedObservable(nameof(model.Map)); var viewportWidthChanged = model.PropertyChangedObservable(nameof(model.ViewportWidth)); var viewportHeightChanged = model.PropertyChangedObservable(nameof(model.ViewportHeight)); var minimapChanged = map.Select( x => x.Match( y => y.PropertyChangedObservable(nameof(y.Minimap)), Observable.Empty <Unit>)) .Switch(); var viewportLocationChanged = map.Select( x => x.Match( y => y.PropertyChangedObservable(nameof(y.ViewportLocation)), Observable.Empty <Unit>)) .Switch(); var startPositionChanged = map.Select( x => x.Match( y => Observable .FromEventPattern <StartPositionChangedEventArgs>( e => y.StartPositionChanged += e, e => y.StartPositionChanged -= e) .Select(z => z.EventArgs.Index), Observable.Empty <int>)) .Switch(); // wire up the simple properties minimapVisible.Subscribe(x => this.MinimapVisible = x); minimap.Subscribe(x => this.MinimapImage = Maybe.From(x)); // listen for changes that affect the minimap viewport rectangle mapChanged.Subscribe(_ => this.UpdateMinimapRectangle()); mapChanged.Subscribe(_ => this.UpdateStartPositions()); minimapChanged.Subscribe(_ => this.UpdateMinimapRectangle()); viewportLocationChanged.Subscribe(_ => this.UpdateMinimapRectangle()); viewportWidthChanged.Subscribe(_ => this.UpdateMinimapRectangle()); viewportHeightChanged.Subscribe(_ => this.UpdateMinimapRectangle()); startPositionChanged.Subscribe(this.UpdateStartPosition); // do the initial rect update this.UpdateMinimapRectangle(); }
public MapViewViewModel(IReadOnlyApplicationModel model, Dispatcher dispatcher, FeatureService featureService) { var heightmapVisible = model.PropertyAsObservable(x => x.HeightmapVisible, nameof(model.HeightmapVisible)); var voidsVisible = model.PropertyAsObservable(x => x.VoidsVisible, nameof(model.VoidsVisible)); var gridVisible = model.PropertyAsObservable(x => x.GridVisible, nameof(model.GridVisible)); var gridColor = model.PropertyAsObservable(x => x.GridColor, nameof(model.GridColor)); var gridSize = model.PropertyAsObservable(x => x.GridSize, nameof(model.GridSize)); var featuresVisible = model.PropertyAsObservable(x => x.FeaturesVisible, nameof(model.FeaturesVisible)); var map = model.PropertyAsObservable(x => x.Map, nameof(model.Map)); var mapWidth = map.ObservePropertyOrDefault(x => x.MapWidth, "MapWidth", 0); var mapHeight = map.ObservePropertyOrDefault(x => x.MapHeight, "MapHeight", 0); this.ViewportLocation = map.ObservePropertyOrDefault( x => x.ViewportLocation, "ViewportLocation", Point.Empty); map.Subscribe(this.SetMapModel); gridVisible.Subscribe(x => this.grid.Enabled = x); gridColor.Subscribe(x => this.grid.Color = x); // FIXME: this should not ignore height gridSize.Subscribe(x => this.grid.CellSize = x.Width); heightmapVisible.Subscribe(this.RefreshHeightmapVisibility); voidsVisible.Subscribe(x => this.voidLayer.Value.Enabled = x); featuresVisible.Subscribe(x => this.featuresVisible = x); this.CanvasSize = mapWidth.CombineLatest(mapHeight, (w, h) => new Size(w * 32, h * 32)); this.CanvasSize.Subscribe( x => { this.guides.ClearGuides(); this.guides.AddHorizontalGuide(x.Height - 128); this.guides.AddVerticalGuide(x.Width - 32); }); map.ObservePropertyOrDefault(x => x.SelectedTile, "SelectedTile", null) .Subscribe(_ => this.RefreshSelection()); map.ObservePropertyOrDefault(x => x.SelectedStartPosition, "SelectedStartPosition", null) .Subscribe(_ => this.RefreshSelection()); map .Where(x => x.IsSome) .Select(x => x.UnsafeValue) // will never be null due to where clause .Select(x => x.SelectedFeatures) .Subscribe(x => x.CollectionChanged += this.SelectedFeaturesCollectionChanged); map.Select( x => x.Match <AbstractLayer>( y => new VoidLayer(y) { Enabled = model.VoidsVisible }, () => new DummyLayer())) .Subscribe(this.voidLayer); this.model = model; this.dispatcher = dispatcher; this.dispatcher.SubscribeToFeatures(this.ItemsLayer); this.featureService = featureService; }
public MainFormViewModel(IReadOnlyApplicationModel model, Dispatcher dispatcher) { var map = model.PropertyAsObservable(x => x.Map, nameof(model.Map)); var mapOpen = map.Select(x => x.IsSome); var isDirty = map.ObservePropertyOrDefault(x => x.IsMarked, "IsMarked", true).Select(x => !x); var filePath = map.ObservePropertyOrDefault(x => x.FilePath, "FilePath", null); var isFileReadOnly = map.ObservePropertyOrDefault(x => x.IsFileReadOnly, "IsFileReadOnly", false); this.CanUndo = map.ObservePropertyOrDefault(x => x.CanUndo, nameof(UndoableMapModel.CanUndo), false); this.CanRedo = map.ObservePropertyOrDefault(x => x.CanRedo, nameof(UndoableMapModel.CanRedo), false); this.CanCut = map.ObservePropertyOrDefault(x => x.CanCut, nameof(UndoableMapModel.CanCut), false); this.CanCopy = map.ObservePropertyOrDefault(x => x.CanCopy, nameof(UndoableMapModel.CanCopy), false); this.CanPaste = map.Select(x => x.IsSome); this.CanFill = map.ObservePropertyOrDefault(x => x.CanCopy, nameof(UndoableMapModel.CanFill), false); this.GridVisible = model.PropertyAsObservable(x => x.GridVisible, "GridVisible"); this.GridSize = model.PropertyAsObservable(x => x.GridSize, "GridSize"); this.HeightmapVisible = model.PropertyAsObservable(x => x.HeightmapVisible, "HeightmapVisible"); this.VoidsVisible = model.PropertyAsObservable(x => x.VoidsVisible, nameof(model.VoidsVisible)); this.FeaturesVisible = model.PropertyAsObservable(x => x.FeaturesVisible, nameof(model.FeaturesVisible)); this.MinimapVisible = model.PropertyAsObservable(x => x.MinimapVisible, nameof(model.MinimapVisible)); this.SeaLevel = map.ObservePropertyOrDefault(x => x.SeaLevel, "SeaLevel", 0); this.CanSaveAs = mapOpen; this.CanCloseMap = mapOpen; this.CanImportMinimap = mapOpen; this.CanExportMinimap = mapOpen; this.CanImportHeightmap = mapOpen; this.CanExportHeightmap = mapOpen; this.CanImportCustomSection = mapOpen; this.CanExportMapImage = mapOpen; this.CanGenerateMinimap = mapOpen; this.CanGenerateMinimapHighQuality = mapOpen; this.CanOpenAttributes = mapOpen; this.CanChangeSeaLevel = mapOpen; // set up CanSave observable var canSave = Observable.CombineLatest( mapOpen, filePath.Select(x => x != null), isFileReadOnly.Select(x => !x)) .Select(x => x.All(y => y)) .Replay(1); canSave.Connect(); this.CanSave = canSave; // set up TitleText observable var cleanFileName = filePath.Select(x => (x ?? "Untitled")); var dirtyFileName = cleanFileName.Select(x => x + "*"); var fileName = isDirty .Select(x => x ? dirtyFileName : cleanFileName) .Switch(); var readOnlyFileName = fileName.Select(y => y + " [read only]"); var fileNameTitle = isFileReadOnly .Select(x => x ? readOnlyFileName : fileName) .Switch(); var defaultTitle = Observable.Return(ProgramName); var openFileTitle = fileNameTitle.Select(y => y + " - " + ProgramName); var titleText = mapOpen .Select(x => x ? openFileTitle : defaultTitle) .Switch() .Replay(1); titleText.Connect(); this.TitleText = titleText; this.dispatcher = dispatcher; }