GithubHelp home page GithubHelp logo

tgjones / gemini Goto Github PK

View Code? Open in Web Editor NEW
1.1K 102.0 293.0 44.47 MB

Gemini is an IDE framework similar in concept to the Visual Studio Shell. It uses AvalonDock and has an MVVM architecture based on Caliburn Micro.

License: Other

C# 99.94% HLSL 0.06%

gemini's Introduction

Gemini Build status NuGet Join the chat at https://gitter.im/tgjones/gemini

Gemini is a WPF framework designed specifically for building IDE-like applications. It builds on some excellent libraries:

Gemini ships with two themes: a Light theme and a Blue theme. There is also an in-development Dark theme.

Screenshot - Light theme

Screenshot - Blue theme

Getting started

If you are creating a new WPF application, follow these steps:

  • Install the Gemini NuGet package.
  • Delete MainWindow.xaml - you don't need it.
  • Open App.xaml and delete the StartupUri="MainWindow.xaml" attribute.
  • Add xmlns:gemini="http://schemas.timjones.tw/gemini" to App.xaml.
  • Add <gemini:AppBootstrapper x:Key="bootstrapper" /> to a ResourceDictionary within <Application.Resources>.

So the whole App.xaml should look something like this:

<Application x:Class="Gemini.Demo.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             xmlns:gemini="http://schemas.timjones.tw/gemini">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <gemini:AppBootstrapper x:Key="bootstrapper" />
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Now hit F5 and see a very empty application!

By far the easiest way to get started with Gemini is to use the various NuGet packages. First, install the base Gemini package (note that the package ID is GeminiWpf, to distinguish it from another NuGet package with the same name):

Then add any other modules you are interested in (note that some modules have dependencies on other modules, but this is taken care of by the NuGet package dependency system):

Continuous builds

We use AppVeyor to build Gemini after every commit to the master branch, and also to generate pre-release NuGet packages so you can try out new features immediately.

To access the pre-release NuGet packages, you'll need to add a custom package source in Visual Studio, pointing to this URL:

https://ci.appveyor.com/nuget/gemini-g84phgw340sm

Make sure you select "Include Prerelease" when searching for NuGet packages.

What does it do?

Gemini allows you to build your WPF application by composing separate modules. This provides a nice way of separating out the code for each part of your application. For example, here is a very simple module:

[Export(typeof(IModule))]
public class Module : ModuleBase
{
	[Import]
	private IPropertyGrid _propertyGrid;

    public override IEnumerable<Type> DefaultTools
    {
        get { yield return typeof(IInspectorTool); }
    }

	public override void Initialize()
	{
		var homeViewModel = IoC.Get<HomeViewModel>();
		Shell.OpenDocument(homeViewModel);

		_propertyGrid.SelectedObject = homeViewModel;
	}

	private IEnumerable<IResult> OpenHome()
	{
		yield return Show.Document<HomeViewModel>();
	}
}

Documents

Documents are (usually) displayed in the main area in the middle of the window. To create a new document type, simply inherit from the Document class:

public class SceneViewModel : Document
{
	public override string DisplayName
	{
		get { return "3D Scene"; }
	}

	private Vector3 _position;
	public Vector3 Position
	{
        get { return _position; }
        set
        {
            _position = value;
            NotifyOfPropertyChange(() => Position);
        }
	}
}

To open a document, call OpenDocument on the shell (Shell is defined in ModuleBase, but you can also retrieve it from the IoC container with IoC.Get<IShell>()):

Shell.OpenDocument(new SceneViewModel());

You can then create a SceneView view, and Caliburn Micro will use a convention-based lookup to find the correct view.

Persisted documents

If you have a document that needs to be loaded from, and saved to, a file, you can use the PersistedDocument base class, to remove a lot of the boilerplate code that you would usually have to write. You only need to implement the DoNew, DoLoad, and DoSave methods.

public class EditorViewModel : PersistedDocument
{
	private EditorView _view;
	private string _originalText;

	protected override Task DoNew()
	{
		_originalText = string.Empty;
		ApplyOriginalText();
		return TaskUtility.Completed;
	}

	protected override Task DoLoad(string filePath)
	{
		_originalText = File.ReadAllText(filePath);
		ApplyOriginalText();
		return TaskUtility.Completed;
	}

	protected override Task DoSave(string filePath)
	{
		var newText = _view.textBox.Text;
		File.WriteAllText(filePath, newText);
		_originalText = newText;
		return TaskUtility.Completed;
	}

	private void ApplyOriginalText()
	{
		_view.textBox.Text = _originalText;

		_view.textBox.TextChanged += delegate
		{
			IsDirty = string.Compare(_originalText, _view.textBox.Text) != 0;
		};
	}

	protected override void OnViewLoaded(object view)
	{
		_view = (EditorView) view;
	}
}

Tools

Tools are usually docked to the sides of the window, although they can also be dragged free to become floating windows. Most of the modules (ErrorList, Output, Toolbox, etc.) primarily provide tools. For example, here is the property grid tool class:

[Export(typeof(IPropertyGrid))]
public class PropertyGridViewModel : Tool, IPropertyGrid
{
	public PropertyGridViewModel()
	{
		DisplayName = "Properties";
	}

	public override PaneLocation PreferredLocation
	{
		get { return PaneLocation.Right; }
	}

	private object _selectedObject;
	public object SelectedObject
	{
		get { return _selectedObject; }
		set
		{
			_selectedObject = value;
			NotifyOfPropertyChange(() => SelectedObject);
		}
	}
}

For more details on creating documents and tools, look at the demo program and the source code for the built-in modules.

Commands

Commands are one of the core concepts in Gemini. Commands help you to avoid duplicating code by letting you define command handlers in a single place, regardless of whether the command is invoked through a menu item, toolbar item, or other trigger. Gemini's commands are conceptually similar to WPF commands, but they are more powerful.

First, create a command definition. Here's Gemini command definition for opening files:

[CommandDefinition]
public class OpenFileCommandDefinition : CommandDefinition
{
	public const string CommandName = "File.OpenFile";

	public override string Name
	{
		get { return CommandName; }
	}

	public override string Text
	{
		get { return "_Open"; }
	}

	public override string ToolTip
	{
		get { return "Open"; }
	}

	public override Uri IconSource
	{
		get { return new Uri("pack://application:,,,/Gemini;component/Resources/Icons/Open.png"); }
	}
	
	[Export]
    public static CommandKeyboardShortcut KeyGesture = new CommandKeyboardShortcut<OpenFileCommandDefinition>(new KeyGesture(Key.O, ModifierKeys.Control));
}

Then, provide a command handler. You can do this in one of two ways. For global commands, that don't depend on a document context, create a global handler:

[CommandHandler]
public class OpenFileCommandHandler : CommandHandlerBase<OpenFileCommandDefinition>
{
	public override void Update(Command command)
	{
		// You can enable / disable the command here with:
		// command.Enabled = true;
		
		// You can also modify the command text / icon, which will affect
		// any menu items or toolbar items bound to this command.
	}
	
	public override async Task Run(Command command)
	{
		// ... implement command handling here
	}
}

For commands that depend on a document context, and should be disabled when there is no active document or the active document is not of the correct type, define the command in the document class:

public class MyDocument : Document, ICommandHandler<ClearTextCommandDefinition>
{
	void ICommandHandler<ClearTextCommandDefinition>.Update(Command command)
	{
		command.Enabled = this.Text.Any();
	}

	Task ICommandHandler<ClearTextCommandDefinition>.Run(Command command)
	{
		this.Text = string.Empty;
		return TaskUtility.Completed;
	}
}

To remove built-in keyboard shortcuts, you can exclude them declaratively:

[Export]
public static ExcludeCommandKeyboardShortcut ExcludeFileOpenShortcut = new ExcludeCommandKeyboardShortcut(OpenFileCommandDefinition.KeyGesture);

To find out how to bind commands to menus or toolbars, see the "MainMenu" and "ToolBars" modules below.

What modules are built-in?

Gemini itself is built out of seven core modules:

  • MainWindow
  • Shell
  • MainMenu
  • StatusBar
  • ToolBars
  • Toolbox
  • UndoRedo

Several more modules ship with Gemini, and are available as NuGet packages as described above:

  • CodeCompiler
  • CodeEditor
  • ErrorList
  • GraphEditor
  • Inspector
  • Output
  • PropertyGrid

For more information about these modules, see below. In general, each module adds some combination of menu items, tool window, document types and services.

MainWindow module

The main window module:

  • manages the overall window

Provides

  • IMainWindow interface

NuGet package

Dependencies

  • None

Usage

The IMainWindow interface exposes a number of useful properties to control aspects of the main application window.

public interface IMainWindow
{
    WindowState WindowState { get; set; }
    double Width { get; set; }
    double Height { get; set; }

    string Title { get; set; }
    ImageSource Icon { get; set; } 

    IShell Shell { get; }
}

Shell module

Screenshot

The shell module:

  • manages placement of the document and tool windows
  • persists and loads the size and position of tool windows
  • manages the links between AvalonDock and Caliburn.Micro

Provides

  • IShell interface

NuGet package

Dependencies

  • None

Usage

The IShell interface exposes a number of useful properties and methods. It is the main way to control Gemini's behaviour.

public interface IShell
{
    event EventHandler ActiveDocumentChanging;
    event EventHandler ActiveDocumentChanged;

    bool ShowFloatingWindowsInTaskbar { get; set; }
        
	IMenu MainMenu { get; }
    IToolBars ToolBars { get; }
	IStatusBar StatusBar { get; }

	IDocument ActiveItem { get; }

	IObservableCollection<IDocument> Documents { get; }
	IObservableCollection<ITool> Tools { get; }

    void ShowTool<TTool>() where TTool : ITool;
	void ShowTool(ITool model);

	void OpenDocument(IDocument model);
	void CloseDocument(IDocument document);

	void Close();
}

MainMenu module

Screenshot

Adds a main menu to the top of the window.

NuGet package

Dependencies

  • None

Usage

First, create commands, as described above in the "Commands" section. Then declare menus, menu item groups, and menu items. This is how the built-in File menu and menu items are declared; you can create your own menus in the same way.

public static class MenuDefinitions
{
    [Export]
    public static readonly MenuDefinition FileMenu = new MenuDefinition(MainMenuBar, 0, Resources.FileMenuText);
	
	[Export]
    public static readonly MenuItemGroupDefinition FileNewOpenMenuGroup = new MenuItemGroupDefinition(FileMenu, 0);
	
	[Export]
    public static readonly MenuItemDefinition FileNewMenuItem = new TextMenuItemDefinition(
        MenuDefinitions.FileNewOpenMenuGroup, 0, "_New");
}

You can either use an existing menu or menu item group as a parent for your menu items, or create your own.

To remove an existing menu item (such as a built-in menu item that you don't want), you can exclude it declaratively:

[Export]
public static readonly ExcludeMenuItemDefinition ExcludeOpenMenuItem = new ExcludeMenuItemDefinition(Gemini.Modules.Shell.MenuDefinitions.FileOpenMenuItem);

[Export]
public static readonly ExcludeMenuItemGroupDefinition ExcludeWindowMenuItemGroup = new ExcludeMenuItemGroupDefinition(Gemini.Modules.MainMenu.MenuDefinitions.ViewToolsMenuGroup);

[Export]
public static readonly ExcludeMenuDefinition ExcludeWindowMenuDefinition = new ExcludeMenuDefinition(Gemini.Modules.MainMenu.MenuDefinitions.WindowMenu);

StatusBar module

Screenshot

Adds a status bar to the bottom of the window.

Provides

  • IStatusBar
  • StatusBarItemViewModel class

NuGet package

Dependencies

  • None

Usage

var statusBar = IoC.Get<IStatusBar>();
statusBar.AddItem("Hello world!", new GridLength(1, GridUnitType.Star));
statusBar.AddItem("Ln 44", new GridLength(100));
statusBar.AddItem("Col 79", new GridLength(100));

ToolBars module

Screenshot

Adds a toolbar tray to the top of the window. By default, the toolbar tray is hidden - use Shell.ToolBars.Visible = true to show it.

NuGet package

Dependencies

  • None

Usage

First, create commands, as described above in the "Commands" section. Then declare toolbars, toolbar item groups, and toolbar items. This is how the standard toolbar and toolbar items are declared; you can create your own toolbars in the same way.

internal static class ToolBarDefinitions
{
	[Export]
	public static ToolBarDefinition StandardToolBar = new ToolBarDefinition(0, "Standard");
	
	[Export]
    public static ToolBarItemGroupDefinition StandardOpenSaveToolBarGroup = new ToolBarItemGroupDefinition(
        ToolBars.ToolBarDefinitions.StandardToolBar, 8);
		
	[Export]
    public static ToolBarItemDefinition OpenFileToolBarItem = new CommandToolBarItemDefinition<OpenFileCommandDefinition>(
        StandardOpenSaveToolBarGroup, 0);
}

// ...

Shell.ToolBars.Visible = true;

Toolbox module

Screenshot

Reproduces the toolbox tool window from Visual Studio. Use the [ToolboxItem] attribute to provide available items for listing in the toolbox. You specify the document type for each toolbox item. When the user switches to a different document, Gemini manages showing only the toolbox items that are supported for the active document type. Items are listed in categories. The toolbox supports drag and drop.

Provides

  • IToolbox tool window
  • ToolboxItemAttribute attribute
  • ToolboxDragDrop utility class

NuGet package

Dependencies

  • None

Usage

[ToolboxItem(typeof(GraphViewModel), "Image Source", "Generators")]
public class ImageSource : ElementViewModel
{
	// ...
}

Handling dropping onto a document (this code is from GraphView.xaml.cs):

private void OnGraphControlDragEnter(object sender, DragEventArgs e)
{
    if (!e.Data.GetDataPresent(ToolboxDragDrop.DataFormat))
        e.Effects = DragDropEffects.None;
}

private void OnGraphControlDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(ToolboxDragDrop.DataFormat))
    {
        var mousePosition = e.GetPosition(GraphControl);

        var toolboxItem = (ToolboxItem) e.Data.GetData(ToolboxDragDrop.DataFormat);
        var element = (ElementViewModel) Activator.CreateInstance(toolboxItem.ItemType);
        element.X = mousePosition.X;
        element.Y = mousePosition.Y;

        ViewModel.Elements.Add(element);
    }
}

UndoRedo module

Screenshot

Provides a framework for adding undo/redo support to your application. An undo/redo stack is maintained separately for each document. The screenshot above shows the history tool window. You can drag the slider to move forward or backward in the document's history.

Provides

  • IHistoryTool tool window
  • IUndoableAction interface
  • UndoRedoToolbarItems utility class

NuGet package

Dependencies

  • None

Usage

First, define an action. The action needs to implement IUndoableAction:

public class MyAction : IUndoableAction
{
    public string Name
    {
        get { return "My Action"; }
    }

    public void Execute()
    {
        // Do something
    }

    public void Undo()
    {
        // Put it back
    }
}

Then execute the action:

var undoRedoManager = IoC.Get<IShell>().ActiveItem.UndoRedoManager;
undoRedoManager.ExecuteAction(new MyAction());

Now the action will be shown in the history tool window. If you are using the Undo or Redo menu items or toolbar buttons, they will also react appropriately to the action.

CodeCompiler module

Uses Roslyn to compile C# code. Currently, ICodeCompiler exposes a very simple interface:

public interface ICodeCompiler
{
    Assembly Compile(
        IEnumerable<SyntaxTree> syntaxTrees, 
        IEnumerable<MetadataReference> references,
        string outputName);
}

An interesting feature, made possible by Roslyn, is that the compiled assemblies are garbage-collectible. This means that you can compile C# source code, run the resulting assembly in the same AppDomain as your main application, and then unload the assembly from memory. This would be very useful, for example, in a game editor where you want the game preview window to update as soon as the user modifies a script source file.

Provides

  • ICodeCompiler service

NuGet package

Dependencies

Usage

This example is from HelixViewModel in one of the sample applications.

var newAssembly = _codeCompiler.Compile(
    new[] { SyntaxTree.ParseText(_helixView.TextEditor.Text) },
    new[]
    {
        MetadataReference.CreateAssemblyReference("mscorlib"),
        MetadataReference.CreateAssemblyReference("System"),
        MetadataReference.CreateAssemblyReference("PresentationCore"),
        new MetadataFileReference(typeof(IResult).Assembly.Location),
        new MetadataFileReference(typeof(AppBootstrapper).Assembly.Location),
        new MetadataFileReference(GetType().Assembly.Location)
    },
    "GeminiDemoScript");

Once there are no references to newAssembly, it will be eligible for garbage collection.

CodeEditor module

Screenshot

Uses AvalonEdit to provide syntax highlighting and other features for editing C# source files.

Provides

  • EditorProvider for C# source files
  • CodeEditor control

NuGet package

Dependencies

Usage

Opening a file with a .cs extension will automatically use the CodeEditor module to display the document. You can also use the CodeEditor control in your own views:

<codeeditor:CodeEditor SyntaxHighlighting="C#" />

ErrorList module

Screenshot

Reproduces the error list tool window from Visual Studio. Can be used to show errors, warning, or information.

Provides

  • IErrorList tool window

NuGet package

Dependencies

  • None

Usage

var errorList = IoC.Get<IErrorList>();
errorList.Clear();
errorList.AddItem(
	ErrorListItemType.Error,
	"Description of the error",
    @"C:\MyFile.txt",
    1,   // Line
    20); // Column

You can optionally provide a callback that will be executed when the user double-clicks on an item:

errorList.AddItem(
	ErrorListItemType.Error,
	"Description of the error",
    @"C:\MyFile.txt",
    1, // Line
    20, // Character
    () =>
    {
        var openDocumentResult = new OpenDocumentResult(@"C:\MyFile.txt");
        IoC.BuildUp(openDocumentResult);
        openDocumentResult.Execute(null);
    });

GraphEditor module

Screenshot

Implements a general purpose graph / node editing UI. This module provides the UI controls - the logic and view models are usually specific to your application, and are left to you. The FilterDesigner sample application (in the screenshot above) is one example of how it can be used.

Although I implemented it slightly differently, I got a lot of inspiration and some ideas for the code from Ashley Davis's CodeProject article.

Provides

NuGet package

Dependencies

  • None

Usage

You'll need to create view models to represent:

  • the graph itself
  • elements
  • connectors
  • connections.

I suggest looking at the FilterDesigner sample application to get an idea of what's involved.

Inspector module

Screenshot

Similar in purpose to the property grid, but the Inspector module takes a more flexible approach. Instead of the strict "two-column / property per row" layout used in the standard PropertyGrid, the Inspector module allows each editor to customise its own view.

It comes with the following editors:

  • BitmapSource
  • CheckBox
  • CollapsibleGroup
  • Color (WPF)
  • Enum
  • Point3D (WPF)
  • Range
  • TextBox

Provides

  • IInspectorTool tool window
  • InspectableObjectBuilder class

NuGet package

Dependencies

Usage

You can build up the inspector for an object in two ways:

  • Convention-based. The Inspector module can reflect over an object and create editors for the properties whose types it recognises. It comes with built-in editors for int, string, Enum, etc.
  • Manually. Use the fluent interface on InspectableObjectBuilder to create editors.

You can also mix and match these approaches.

var inspectorTool = IoC.Get<IInspectorTool>();
inspectorTool.SelectedObject = new InspectableObjectBuilder()
	.WithCollapsibleGroup("My Group", b => b
		.WithColorEditor(myObject, x => x.Color))
	.WithObjectProperties(Shell.ActiveItem, pd => true) // Automatically adds browsable properties.
	.ToInspectableObject();

Output module

Screenshot

Much like the output tool window from Visual Studio.

Provides

  • IOutput tool window

NuGet package

Dependencies

  • None

Usage

var output = IoC.Get<IOutput>();
output.AppendLine("Started up");

PropertyGrid module

Screenshot

Pretty much does what it says on the tin. It uses the PropertyGrid control from the Extended WPF Toolkit.

Provides

  • IPropertyGrid tool window

NuGet package

Dependencies

Usage

var propertyGrid = IoC.Get<IPropertyGrid>();
propertyGrid.SelectedObject = myObject;

Sample application

Gemini.Demo showcases many of the available modules. The screenshot below shows the interactive script editor in action - as you type, the code will be compiled in real-time into a dynamic assembly and then executed in the same AppDomain.

It also includes a very basic example of a filter designer, built on the GraphEditor module.

Screenshot

What projects use Gemini?

I've used Gemini on several of my own projects:

Acknowledgements

  • Many of the original ideas, and much of the early code came from Rob Eisenberg, creator of the Caliburn Micro framework. I have extended and modified his code to integrate better with AvalonDock 2.0, which natively supports MVVM-style binding.
  • I used the VS2010 theme from Edi.

Gemini is not the only WPF framework for building IDE-like applications. Here are some others:

gemini's People

Contributors

4ux-nbix avatar crowbar27 avatar diluculo avatar echterago avatar florenzetti avatar gmich avatar greenboxal avatar insanekitty avatar jetelain avatar jie2gg avatar kornman00 avatar krisjanssen avatar luuksommers avatar lymims avatar mikirasora avatar nesterenko-kv avatar oldno7 avatar reminoer avatar ryanvs avatar sblkr avatar simie avatar tgjones avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gemini's Issues

MenuItem or ToolbarItem commands still execute even if item is disabled when using Global Shortcuts

I have a MenuItem with a Global Shortcut and the MenuItem is disabled. Obviously clicking on the disabled MenuItem does nothing , but if I use the shortcut, e.g: Ctrl+S, the command behind the MenuItem gets called, irrespective of if the MenuItem can be executed or not - even if there is no active document. It seems as though the command does not get enabled/disabled when the MenuItem can execute or not.

This is applicable to ToolbarItems as well as MenuItems

Advice on how Best to Execute IDocument Specific Behaviors on KeyGestures

I love this framework, it has taken me a while to get my teeth stuck into it, but now my development is flying along!

Despite the above, i am trying to do something simple and failing. All I want to do is add a ToolBar button that saves the current document. To do this I have added a Save method to IDocument and add the ToolBar items like

Shell.ToolBars.Items.Add(new ToolBarModel
{
    new ToolBarItem("Open", OpenFile)
        .WithVectorGraphic("appbar_folder")
        .WithGlobalShortcut(ModifierKeys.Control, Key.O),
    ToolBarItemBase.Separator,
    new ToolBarItem("Save", SaveFile)
        .WithVectorGraphic("appbar_book")
        .WithGlobalShortcut(ModifierKeys.Control, Key.S)
        .WithToolTipText("ToolTip Text")
});

where OpenFile is as-per Gemini core code

private IEnumerable<IResult> OpenFile()
{
    var dialog = new OpenFileDialog();
    yield return Show.CommonDialog(dialog);
    yield return Show.Document(dialog.FileName);
}

My problem is my SaveFile method. All I want to do is

public async Task SaveFile()
{
    IDocument document = Shell.ActiveItem;
    try
    {
        mainWindow = IoC.Get<IMainWindow>();
        mainWindow.Shell.StatusBar.Items[(int)StatusBarItem.StatusMessage].Message =
            String.Format("Writing to file '{0}'...", document.FilePath);
        mainWindow.ProgressVisibility = System.Windows.Visibility.Visible;
        await Task.Factory.StartNew(() => document.Save());
    }
    finally
    {
        mainWindow.Shell.StatusBar.Items[(int)StatusBarItem.StatusMessage].Message = "Ready";
        mainWindow.ProgressVisibility = System.Windows.Visibility.Collapsed;
    }
}

but I can't as the ToolBar constructor expects a Func<IEnumerable<IResult>>.

Why is this implemented this way, and how can I use this sort of action to do as I want?

I am tempted to write a wrapper to give me what I need

public class LambdaResultAsync : IResult
{
    private readonly System.Action action;

    /// <summary>
    /// Default constructor.
    /// </summary>
    /// <param name="action">The action to be executed.</param>
    public LambdaResultAsync(System.Action action)
    {
        this.action = action;
    }

    /// <summary>
    /// Execute the required action on a background thread.
    /// </summary>
    /// <param name="context">The execution context.</param>
    public async void Execute(CoroutineExecutionContext context)
    {
        await Task.Factory.StartNew(() => action());
        Completed(this, new ResultCompletionEventArgs());
    }

    /// <summary>
    /// Event handler for the task completion.
    /// </summary>
    public event EventHandler<ResultCompletionEventArgs> Completed;
}

But am I missing something?
Thanks for your time.

Need to learn the source code of "Merlin Editor"

Hi ,I download the source code of Gemini .But in the source code ,I can not find the source code of the "Merlin Editor" . I want to design a 3dmax like IDE using Gemini,the "Merlin Editor" is very similar to my aim. Can you provide the "Merlin Editor" source code? Or provide the download Url? My Gmail is [email protected] .Thanks a lot.

Turn Gemini.Modules.Metro into a theme, and create interface for Gemini themes

As per @4ux-nbIx's suggestion in #57:

By the way, since we're talking about theming here, I wanted to share another idea. Looking at Gemini.Metro module I think that it should be a theme actually, i.e. it should be able to provide a resource dictionary with all it's nice stuff, like current Gemini themes, and it should also be able to hook into Caliburn.Micro WindowManager to provide MetroWindow instances instead of normal windows. So I suggest to make themes a little smarter, i.e. it should be some MEF exported interface with a name and may be some other useful properties and an ability to integrate into the app as deep as they need to. This way it'll be at least possible to gather all available themes and display a combo box in options dialog. What do you think.

How to Show (Login) Window before MainWindow display

Hi, Tgjones:

Our group want to make a program looks like "Photoshop" with some 3d render functions. So we find Gemini is our best choice.

But when I try to show a (Login) window, or config window before MainWindow start, I met some difficulty. I found the IWindow interface, and what to do something, but all my attempts failed over the past 12 hours!

I konw it's a simple function, but maybe I gone the wrong way. Could you please help me? Thanks a lot.

OpenDocumentResult to call OnCompleted immediately, not on deactivation of document

My problem is that currently I could not execute any action on the opened document.
For example, I open document, than I would like to load document from file and after that I'd like to parse the file content with parser (to make custom highlight).

But action execution just "hangs" on the line "yield return Show.Document(document);" - that is because OpenDocumentResult threats action completion as moment when user closes the tab.

I understand justification of such behavior for showing modal dialogs, where after showing a dialog, if result of the dialog was successful, another operation may need to be run, but operations of opening textual files does not need such behavior.

So, it would be nice to have, at least, an option - if after activating the document result is completed or it shall wait on document deactivation.

Changed Namespaces, Style Templates in GraphEditor can't be located?

Hi Tim,

First - thanks for sharing. I've been tinkering for a while now and I'm starting to understand how things work a little better than last year.

I'm trying to develop an application with a new module similar to the FilterDesigner module, but I'm hitting a brick wall. In my infinite wisdom, I changed the namespaces to match paradigm I have going with other solutions of mine (so I'm sure this is all my fault). I have things "mostly" working at this point, but I'm wondering if you can shed some light on the subject.

The behavior of the problem was that when I loaded a new document (of new module type), I received an exception. I tracked the issue down to Gemini.Modules.GraphEditor.ZoomAndPanControl\OnApplyTemplate. "_content" had not been set to anything and its value was 'null'. This can be reproduced by commenting out a Style in Themes\Generic.xaml

I added a quick one-line fix to verify that "_content" was set before trying to access it, then continued researching.

I eventually figured out that my new module (in the "demo" EXE) could not locate the Style in the NewNamespace.Module.GraphEditor project. I can get around this exception by copying Generic.xaml to my "demo" project and adding local reference to it in the MergedDictionary section of App.xaml.

I can then see the Graph when I load a document.

My issue at this point is that I cannot get any "Elements" added to the Graph. Drag/Drop causes my new module's DynamicElement to be instanced, but it never appears on the Graph.

I have exhausted Google - most posts claim adding "ThemeInfo" to the AssemblyInfo will solve this, but it is already there (Gemini.Demo.FilterDesigner was the template).

Any ideas/advice?

If you have no idea, "change the namespaces back" would be an acceptable answer.

Thanks.

Clearing Menu on startup causes error.

I used the demo app as a starting point for the application I am writing. I don't want a main menu for this application so I put the following code in the startup module.

    public override void PostInitialize()
    {
        MainMenu.Clear();
    }

This worked as of 0.5.0. When I installed 0.6.0 it crashes the application before it get's started.

I pulled the gemini project from github and edited the demo app and found it fails in the AppBootstrapper.

        DisplayRootViewFor<IMainWindow>();

An unhandled exception of type 'System.ArgumentNullException' occurred in WindowsBase.dll
Additional information: Value cannot be null.

Looking for Chinese friends, develop Gemini projects together. 寻找用Gemini ide做开发的**朋友,一起开发项目。

寻找用Gemini ide做开发的**朋友,一起开发项目。我在湖北武汉,用Gemini ide开发一个类似3dsmax的项目,遇到了很多的困难,望能有同样爱好的朋友联系我,我们一起开发。如果需要费用,我可以和单位商量以劳务费的方式提供报酬。请有意者联系我:QQ 550672121 Tel:13545039686
事情紧急,没有办法,只能在此发帖,请楼主不要删除这个帖子。谢谢。

Looking to do with the development of the Chinese Gemini ide friends, develop projects together. I was in Wuhan, with Gemini ide 3dsmax developing a similar project encountered many difficulties, hope to have the same loving friends contact me, we have developed together. If necessary expenses, I can talk to and unit labor costs in the way of providing compensation. Interested parties please contact me: QQ 550672121 Tel: 13545039686
Urgency of the matter, there is no way, only in this post, please do not delete this post landlord. Thank you.

IShell to expose list of opened documents (and possible tools)

It would be good to get access to list of currently opened documents. I could cast IShell to IParent, but that is bad, because it is assumption on implementation of IShell, it would be much better if either IShell be derived from IParent or expose property ICollection Documents or even both.

PS: Awesome framework! It's really a time saver...

LoadState doesn't use IEditorProvidors to load documents

LoadState is opening empty document windows that aren't using my defined IEditorProvidors to populate them. I would assume that when the shell restores my state that it would use the providers to populate them, but break points are indicating that they are not.

EDIT: I figured it out. For anyone else who comes across this later looking for an answer. I needed to add an export to my document class, and then override LoadState and SaveState in the class. the code editor demo shows how to do this.

Beta builds, please

It would be really helpful to have beta Gemini packages available in NuGet after merging a pull request or after some significant changes to the source code. This way developers will be able to leverage NuGet package update in their projects right after they contribute to Gemini.

3d draw

Hi all!
I've made my parser to my 3d library, that actually needs an handle of the object to draw it (this in winforms projects)
how can I do this thing using gemini? I wish a thing like xna demo!

thanks in advance

Error when docking

Sometimes the docking fails. I have recreated the error in the sample Project.

Just start the sample Project (make sure that the file ApplicationState.bin is deleted) and then take the Inspector tool pane and drop it on the lower or upper part of the compass in the middle. The whole document pane disappears and nothing but application shutdown works. Attached is an image that decribes where to drop the pane. If you start the application again the pane is located at the bottom but with no height. To recreate the issue you need to delete ApplicationState.bin.
gemini-dock

Enable localisation of menus

Hi,

I recently stumbled over this project and I like it very much. Thank you for your work.

However, I have some problems, because I need to localise my application. In order to do so, it would be great if the name of a menu item was independent from its text. I do not know whether the name "-" in MenuItemBase is required, but if not, something like this would be great:

In MenuItemBase:

private string name;
public virtual string Name {
    get {
        return this._name;
    }
    set {
        this.name = value;
        this.NotifyOfPropertyChange(() => this.Name);
    }
}

In StandardMenuItem:

public override string Name {
    get {
        return base.Name ?? (string.IsNullOrEmpty(Text) ? null : Text.Replace("_", string.Empty));
    }
}

This implementation would break anything that relies on the default name being "-", but would be compatible in all other cases and enable setting localised captions for the menu items.

Consider exposing menu items and toolbar buttons using [Export] attributes

The Visual Studio approach is described here:
http://dotneteers.net/blogs/divedeeper/archive/2008/02/22/LearnVSXNowPart13.aspx

I don't propose anything nearly as complicated as the VS approach, but I do like the idea of exposing menu items, and toolbar buttons through MEF Export attributes, to be pulled in by the MainMenu and ToolBar modules, instead of "pushing" menu items using MainMenu.Add, etc.

It would also make it easier to completely disable the MainMenu and ToolBar modules.

(VS has the concept of commands - as I understand it, a single command can be bound to both a menu item and a toolbar button, which nicely centralises the command handler. I think we already have a lot of these advantages just by using WPF / Caliburn Micro, but it's an idea.)

Any thoughts?

How to handle attempt to close application?

I need to query user about need to save changes before application close.
I implemented CanClose for view models of documents and query if user would like to Save,Discard or Cancel closing.

That works, but here are the problems:

  • When multiple documents are opened, user need to go though a lot of confirmation dialogs. It would be better to be able to show one dialog with all unsaved files.
  • There are invisible items which should be saved (like project file, it is not opened as document, but, nevertheless, should be saved)

The appropriate way to do that in Caliburn.Micro is to implement CanClose for ShellViewModel. I tried nesting the ShellViewModel and override CanClose method, but faced impossibility to substitute original ShellViewModel with my variant in MEF container.

I ended up with the following solution:

Application.Current.MainWindow.Closing += (sender, args) =>
{
....
};

But that does not look like a code which plays well with Caliburn.Micro and Gemini...

Do you have advice how to do that better?

How to customize the Gemini ide

Hi

I download the Gemini sourcecode. Run it in such enviroment:Win7,Visual studio 2012.

I want to customize the ide UI. So I did like this:

To customize Gemini.Demo.FilterDesigner UI,I go to the Gemini.Modules.Inspector source code , and find the Module.cs file,Open the c# source code,I fine the code like this:

public override void Initialize()
{
MainMenu.All.First(x => x.Name == "View")
.Add(new MenuItem("Inspector", OpenInspector));
}

I note the source code,then the code like this:

public override void Initialize()
{
//MainMenu.All.First(x => x.Name == "View")
//.Add(new MenuItem("Inspector", OpenInspector));
}

Then run the solution ,and set the Gemini.Demo.FilterDesigner as the StartOne project.When it runs, I find in Main menu ,in the View menu ,the "Inspector" disapeared. It is just I want to have.

But when the program runs ,I find the "Inspector"tool box is aready loaded and settled to the right of the windows,I want the "Inspector" tool box will not loaded when the program runs ,How can I customize the source code?

Needs help ,thanks a lot.

Floating window doesn't show up in task bar

Is there a way to show floating window in task bar so that we can activate/show just this window from taks bar? I read that there is a property called "ShowInTaskb", and setting it to true would achieve this goal, but I couldn't figure out where to add it. Please advise. Ideally we should make this feature optional and can be configured from app.config or set programmatically. Thanks a lot for this great project!

How to Add a Document Windows to the Gemini.Demo Project

Hi

I need add a Document Window just like the HomeView Windows to the Gemini.Demo project and custumize the Menu items.I custumized three place in the Gemini.Demo project,the detail :

In Gemini.Demo.Modules.Home.Views
I added a WPF usercontrol,the file name is LzhEyeForModView.xaml,the code:

<UserControl x:Class="Gemini.Demo.Modules.Home.Views.LzhEyeForModView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

         xmlns:WinFormHost="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"  
         xmlns:WinFormControls="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
         xmlns:LzhCtlforEye="clr-namespace:lzhWinFromCtlforEyeModel;assembly=lzhWinFromCtlforEyeModel"

         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <WinFormHost:WindowsFormsHost HorizontalAlignment="Left" Height="258" Margin="20,20,0,0" VerticalAlignment="Top" Width="260">

        <LzhCtlforEye:UserControl1 Height=" 100" Width="100"/>

    </WinFormHost:WindowsFormsHost>
</Grid>
In Gemini.Demo.Modules.Home.ViewModels
I added a class,the file name is LzhEyeForModViewModel.cs,the code is:

using Gemini.Framework;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Gemini.Demo.Modules.Home.ViewModels
{
[DisplayName("Home View Model")]
[Export(typeof(HomeViewModel))]
public class LzhEyeForModViewModel : Document
{

    public LzhEyeForModViewModel()
    {
        DisplayName = "三维建模";
    }
}

}

In the Gemini.Demo.Modules.Home
I custumize the Module.cs file, the code is:

using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Caliburn.Micro;
using Gemini.Demo.Modules.Home.ViewModels;
using Gemini.Framework;
using Gemini.Framework.Results;
using Gemini.Modules.MainMenu.Models;
using Gemini.Modules.PropertyGrid;

namespace Gemini.Demo.Modules.Home
{
[Export(typeof(IModule))]
public class Module : ModuleBase
{
[Import]
private IPropertyGrid _propertyGrid;

    public override IEnumerable<IDocument> DefaultDocuments
    {
        get
        {
            yield return IoC.Get<HomeViewModel>();
            yield return IoC.Get<HelixViewModel>();
            yield return IoC.Get<LzhEyeForModViewModel>();

        }
    }

    public override void Initialize()
    {
        MainMenu.All
            .First(x => x.Name == "View")
            .Add(new MenuItem("欢迎", OpenHome));

        MainMenu.All
            .First(x => x.Name == "View")
            .Add(new MenuItem("螺旋管", OpenHelix));
        MainMenu.All
            .First(x => x.Name == "View")
            .Add(new MenuItem("三维建模", OpenLzhEyeForMod));
    }

    public override void PostInitialize()
    {
        _propertyGrid.SelectedObject = IoC.Get<HomeViewModel>();
        Shell.OpenDocument(IoC.Get<HomeViewModel>());
    }

    private IEnumerable<IResult> OpenHome()
    {
        yield return Show.Document<HomeViewModel>();
    }

    private IEnumerable<IResult> OpenHelix()
    {
        yield return Show.Document<HelixViewModel>();
    }

    private IEnumerable<IResult> OpenLzhEyeForMod()
    {
        yield return Show.Document<LzhEyeForModViewModel>();
    }
}

}
When the prog runs,it comes out errors:
The errors turn out in App.xaml,
The errors code is:<gemini:AppBootstrapper x:Key="bootstrapper" />
And the errors is:对类型“Gemini.AppBootstrapper”的构造函数执行符合指定的绑定约束调用时引发了异常
image

  My problem is : I do not custumize the App.xaml source code, why it turns error? How can I add a document window to the Gemini.Demo project ?

get notified when property changes

hi all!
In my viewModel I've added this property:

private Point3D _timeOfDay;
[DisplayName("Time Of The Day"), Description("Sunrise, Current Time, Sunset")]
public Point3D TimeOfDay
{
    get { return _timeOfDay; }
    set
    {
        _timeOfDay = value;
        NotifyOfPropertyChange(() => TimeOfDay);
    }
}

and I need to be notified in my cs code when the TimeOfDay property is changed by the inspector...
how can I do this?

I've tried to do this:

DataContext = new HomeViewModel();
((HomeViewModel)DataContext).PropertyChanged +=HomeView_PropertyChanged;

but doesn't work...
thanks in advance

Dragging ToolBarItems Causes Binding and Display Failures

I have come across two problems with the current ToolBar styling:

A. The tool bar images are currently getting used as a single static instance. Even with the property x:Shared="False" moving the ToolBar one over another will cause a rendering failure.

imageerror

Solution:

In the ToolTip Styles.xaml, include the image source as a ContentTemplate

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:cal="http://www.caliburnproject.org">
    <Style x:Key="ToolBarToggleButton" TargetType="{x:Type ToggleButton}" 
           BasedOn="{StaticResource {x:Static ToolBar.ToggleButtonStyleKey}}">
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Image x:Shared="false" Source="{Binding Icon}">
                        <Image.Style>
                            <Style TargetType="Image">
                                <Setter Property="Width" Value="16" />
                                <Setter Property="Height" Value="16" />
                                <Setter Property="Stretch" Value="Fill" />
                                <Style.Triggers>
                                    <Trigger Property="IsEnabled" Value="False">
                                        <Setter Property="Opacity" Value="0.5" />
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                </DataTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ToolTip" Value="{Binding FullToolTip}" />
        <Setter Property="ToolTipService.IsEnabled" Value="{Binding HasToolTip}" />
        <Setter Property="IsChecked" Value="{Binding IsChecked}" />
        <Setter Property="cal:Action.Target" Value="{Binding}" />
        <Setter Property="cal:Message.Attach" Value="{Binding ActionText}" />
    </Style>

    <Style x:Key="ToolBarButton" TargetType="{x:Type Button}" 
           BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Image x:Shared="false" Source="{Binding Icon}">
                        <Image.Style>
                            <Style TargetType="Image">
                                <Setter Property="Width" Value="16" />
                                <Setter Property="Height" Value="16" />
                                <Setter Property="Stretch" Value="Fill" />
                                <Style.Triggers>
                                    <Trigger Property="IsEnabled" Value="False">
                                        <Setter Property="Opacity" Value="0.5" />
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                </DataTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ToolTip" Value="{Binding FullToolTip}" />
        <Setter Property="ToolTipService.IsEnabled" Value="{Binding HasToolTip}" />
        <Setter Property="cal:Action.Target" Value="{Binding}" />
        <Setter Property="cal:Message.Attach" Value="{Binding ActionText}" />
    </Style>
</ResourceDictionary>

Now we have:

imageerrorsolved

No other changes required.

B. When the drag operation shown above occurs, this also breaks the Message.Attach and ToolTip bindings.

I have not yet got a solution to this one as I have just found it. I will work on this tonight and provide an update in due course.

How to Add a Document Window to the Gemini.Demo Project Continued

Thanks to Boss's help. But my errors still comes out. I change the code,Now the code in ViewModels is:
image
The errors is :
image

As your direct,I readed the detail of the errors,but can not find some ways to do it .

Maybe someplace in Gemini.Demo I need to Custumize, but I can not find the place,please give me some introduction.Thanks a lot.

Opening Tool if already loaded on startup causes multiple tools.

Steps to reproduce:

  1. Run demo project(s)
  2. Open any tool from menu (toolbox, output, etc.)
  3. Close
  4. Restart
  5. Select tool from menu again

Thought a workaround would be to check for existence of tool in Shell.Tools collection, but the collection does not seem to be refreshed upon startup (guessing the items are loading via AvalonDock.Layout file).

Use of MonoGame

Is it possible that you create also a Example with MonoGame?

I tried to switch from XNA to MonoGame myself, but I could not get it working!

Since XNA is no longer Developed, and MonoGame is nearly API compatible it would be nice if you support this also.

ToolbarItem Tooltip - need more info

How can the Tool Tips for ToolBarItem's display more than just the Global shortcut key (if provided)?
Scenario:
Create a ToolBarItem: var runItem = new ToolBarItem("Run", Run, CanRun).WithIcon();
Result: A toolbar item with the correct Icon is added into my ToolbarModel, but the tooltip is blank/empty.

If I add the below line to that statement, the tooltip with the Hotkey/Shortcut is displayed.
.WithGlobalShortcut(System.Windows.Input.ModifierKeys.None, System.Windows.Input.Key.F5)

Now what about the Text/Name of the ToolBarItem? Surely that should be displayed in the tooltip when an Icon is used?

ApplicationState.bin file is created in working directory instead of executable file direcotry.

Path of the state file is hard-coded like .\ApplicationState.bin where dot is resolved into working directory of the current process. Which may not always be the same folder where executable is located.

The case is when application which uses Gemini is associated with the certain type of file. When you double click on this file the application is launched with directory of that file set as working directory of the application process which leads to ApplicationState.bin being saved into that directory. Every time you open file with an Gemini app there state file is persisted in that folder.

It would be really great if Gemini allowed to specify location of ApplicationState.bin file or at least always save it to executable file directory (AppDomain.CurrentDomain.BaseDirectory)

Gentle push (or a shove) in the right direction needed.

I'm trying to use this framework, but would like to use a Ribbon (i.e. http://fluent.codeplex.com/ or equivalent) instead of the built in Menu/Toolbar. They require inheritance from an base class other than System.Windows.Window.

I actually hacked it together, but am wondering how best to implement "for real" and could use some guidance.

Does anyone have an example of how to override IShell to exclude MainMenu/Toolbars/StatusBar?

Or perhaps an example of how to load a custom "ShellView", contained in the "application" from the bootstrapper?

No way to change/remove default menubar items

The MainMenu module implements a basic menu structure. If I don't wish to use this structure, there does not appear to be any easy way to override it.

For example, I wanted to change the Open item's Name to "Open Project" but there is no setter.

I tried to remove the open item, but that seems to break the internals and I get "sequence does not contain element" errors.

Am I missing something? Is there an easy way to override the default MainMenu setup?

Making sense of Inspector module approach

Okay, first thing first: gemini project is great! Thank you @tgjones for your work!

I'm using gemini Inspectors module in my app.
My problem is, that i can see the inspector, generated with documentation approach, but the values i edit doesnt update my ViewModel and i cant understand what is wrong even after browsing gemini source code and FilterDesigner demo.

So, my basic approach is:

  1. Create the ViewModel class that have string "Name" property and implements "INotifyPropertyChanged"
  2. When this ViewModel is selected i manualy create inspector for "Name" property using "InspectableObjectBuilder" class and "WithObjectProperties" method, passing apropriate property filter labda.
    I can see "Name" property editor with actual value after that.
  3. I change property value in editor and nothing happens (though property setter is public).

So what did i miss?

Binding Failure on ToolBar Container Dragging

I have come across three problems with the current ToolBar styling:

First:

The tool bar images are currently getting used as a single static instance. Even with the property x:Shared="False" moving the ToolBar one over another will cause a rendering failure.

imageerror

Solution:

In the ToolTip Styles.xaml, include the image source as a ContentTemplate

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:cal="http://www.caliburnproject.org">
    <Style x:Key="ToolBarToggleButton" TargetType="{x:Type ToggleButton}" 
           BasedOn="{StaticResource {x:Static ToolBar.ToggleButtonStyleKey}}">
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Image x:Shared="false" Source="{Binding Icon}">
                        <Image.Style>
                            <Style TargetType="Image">
                                <Setter Property="Width" Value="16" />
                                <Setter Property="Height" Value="16" />
                                <Setter Property="Stretch" Value="Fill" />
                                <Style.Triggers>
                                    <Trigger Property="IsEnabled" Value="False">
                                        <Setter Property="Opacity" Value="0.5" />
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                </DataTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ToolTip" Value="{Binding FullToolTip}" />
        <Setter Property="ToolTipService.IsEnabled" Value="{Binding HasToolTip}" />
        <Setter Property="IsChecked" Value="{Binding IsChecked}" />
        <Setter Property="cal:Action.Target" Value="{Binding}" />
        <Setter Property="cal:Message.Attach" Value="{Binding ActionText}" />
    </Style>

    <Style x:Key="ToolBarButton" TargetType="{x:Type Button}" 
           BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Image x:Shared="false" Source="{Binding Icon}">
                        <Image.Style>
                            <Style TargetType="Image">
                                <Setter Property="Width" Value="16" />
                                <Setter Property="Height" Value="16" />
                                <Setter Property="Stretch" Value="Fill" />
                                <Style.Triggers>
                                    <Trigger Property="IsEnabled" Value="False">
                                        <Setter Property="Opacity" Value="0.5" />
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                </DataTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ToolTip" Value="{Binding FullToolTip}" />
        <Setter Property="ToolTipService.IsEnabled" Value="{Binding HasToolTip}" />
        <Setter Property="cal:Action.Target" Value="{Binding}" />
        <Setter Property="cal:Message.Attach" Value="{Binding ActionText}" />
    </Style>
</ResourceDictionary>

Now we have:

imageerrorsolved

No other changes required.

Second:

The same dragging procedure the ToolTip and ToolTipService bindings also get corrupted - at this stage I am not sure of the underlying reason. The quick solution is to do what I have done with the image above and add the ToolTip to the Image. However, this causes the ToolTip only to show when over the Image and not when hovering over the very edge of the button.

Partial Solution:

Add the ToolTip to the Image.

Third:

When the drag operation shown above occurs, this also breaks the Caliburn property bindings

<Setter Property="cal:Action.Target" Value="{Binding}" />
<Setter Property="cal:Message.Attach" Value="{Binding ActionText}" />

I have not yet got a solution to this one as I have just found it. I will work on this tonight and provide an update in due course, but if anyone can help with this as I am new to WPF, it would be appreciated.

ToolboxItem Icon

I noticed that the Sigma Icon is the default icon for all ToolboxItems and there is an IconSource URI property in the ToolboxItemViewModel class. Is there a way to set the Icon for ToolboxItems instead of using the default?

Begging for open Merlin Editor's source code

Unit project urgent need to do a simple version of 3dsmax.Originally intended to be developed based gemini, but we have little foundation, the process being blocked.Merlin Editor is very similar to our aims, so We Begging for open Merlin Editor's source code,We are very eager to learn the experience of the project.
Begging beggin .....Thanks Thanks......

How to skin the StatusBar and the ToolBar using MahApps Metro

All, I am having difficulty attempting to style the ToolBar and StatusBar using MahApps metro. There is an example of how to do this for the main window, but I can seem to apply the same principles to skin the Tool/Status bars. Can anyone point me in the right direction here please?

Document.CloseCommand CanExecute calls CanClose

From the Caliburn Micro docs:

CanClose – The default implementation always allows closing. Override this method to add custom guard logic.
TryClose – Call this method to close the screen. If the screen is being controlled by a Conductor, it asks the Conductor to initiate the shutdown process for the Screen. [...] In both scenarios the CanClose logic will be invoked and if allowed, OnDeactivate will be called with a value of true.

It seems the intended behavior is for CanClose to display warnings such as "Do you want to save" etc, which makes it unsuitable for a CanExecute callback.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.