/* Ribbon.cs * part of zaaReloaded2 * * Copyright 2015 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.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Windows; using System.Drawing; using System.Windows.Resources; using Office = Microsoft.Office.Core; using zaaReloaded2.Views; using zaaReloaded2.ViewModels; using zaaReloaded2.Importer.ZaaImporter; using zaaReloaded2.Formatter; using zaaReloaded2.Controller; using Word = Microsoft.Office.Interop.Word; using Bovender.Mvvm.Actions; // TODO: Follow these steps to enable the Ribbon (XML) item: // 1: Copy the following code block into the ThisAddin, ThisWorkbook, or ThisDocument class. // protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject() // { // return new Ribbon(); // } // 2. Create callback methods in the "Ribbon Callbacks" region of this class to handle user // actions, such as clicking a button. Note: if you have exported this Ribbon from the Ribbon designer, // move your code from the event handlers to the callback methods and modify the code to work with the // Ribbon extensibility (RibbonX) programming model. // 3. Assign attributes to the control tags in the Ribbon XML file to identify the appropriate callback methods in your code. // For more information, see the Ribbon XML documentation in the Visual Studio Tools for Office Help. namespace zaaReloaded2 { [ComVisible(true)] public class Ribbon : Office.IRibbonExtensibility { #region Constructor public Ribbon() { } #endregion #region IRibbonExtensibility Members public string GetCustomUI(string ribbonID) { return GetResourceText("zaaReloaded2.Ribbon.xml"); } #endregion #region Ribbon Callbacks //Create callback methods here. For more information about adding callback methods, visit http://go.microsoft.com/fwlink/?LinkID=271226 public void Ribbon_Load(Office.IRibbonUI ribbonUI) { _ribbon = ribbonUI; Microsoft.Office.Interop.Word.Application word = Globals.ThisAddIn.Application; word.WindowSelectionChange += Application_WindowSelectionChange; } /// /// Handles ribbon button clicks. This method also contains the try...catch /// structure that invokes the central exception handler in the event of an /// exception. /// /// public void Ribbon_Click(Office.IRibbonControl control) { try { switch (control.Id) { case "zrlFormat": DoFormat(); break; case "zrlSettings": DoChooseSettings(); break; case "zrlAbout": ViewModels.AboutViewModel vm = new ViewModels.AboutViewModel(); vm.InjectInto().ShowDialog(); break; case "zrlDaniel": Formatter.DanielsStyle.Apply( Globals.ThisAddIn.Application.ActiveDocument, Globals.ThisAddIn.Application.Selection); break; case "zrlDemo": DoLoadDemo(); break; default: throw new InvalidOperationException("No operation defined for " + control.Id); } } catch (Exception e) { Bovender.ExceptionHandler.CentralHandler.Manage(this, e); } } /// /// Returns an Image object for the ribbon. /// /// /// The image file is expected to be a WPF resource file, not an embedded resource. /// To be consistent accross the application which uses WPF resources for its WPF /// windows, all images are to be built as resources rather than embedded resources. /// /// The file name (without path) of the image. /// Image object public object Ribbon_LoadImage(string imageId) { string initPackScheme = System.IO.Packaging.PackUriHelper.UriSchemePack; StreamResourceInfo sri = Application.GetResourceStream( new Uri(@"pack://application:,,,/zaaReloaded2;component/Icons/" + imageId)); return Image.FromStream(sri.Stream); } public bool Daniel_GetVisible(Office.IRibbonControl control) { switch (Environment.UserName.ToUpper()) { case "DANIEL": case "KRAUS_D1": return true; default: return false; } } /// /// Returns true if there is at least one paragraph selected. /// /// /// The Selection object in Word is a bit tricky: Its Length property /// is never 0, because even if no text passage is selected, the character /// after the cursor is the content of the Selection. /// public bool CanFormat(Office.IRibbonControl control) { return Globals.ThisAddIn.Application.ActiveDocument != null; //Word.Selection s = Globals.ThisAddIn.Application.ActiveWindow.Selection; //return s.Paragraphs.Count > 1 || // (s.Text.Length > 1 && s.Text.EndsWith("\r")); } #endregion #region Private methods void DoFormat() { // If no "real" selection exists, attempt to auto-detect the lab data. // (NB Technically, there is never _no_ selection in a document.) Word.Window activeWindow = Globals.ThisAddIn.Application.ActiveWindow; Word.Selection sel = activeWindow.Selection; if (!(sel.Paragraphs.Count > 1 || (sel.Text.Length > 1 && sel.Text.EndsWith("\r")))) { if (!AutoDetect.Detect(activeWindow.Document)) { NotificationAction a = new NotificationAction(); a.Caption = "Formatieren nicht möglich"; a.Message = "Das Dokument scheint keine Lauris-Labordaten zu enthalten."; a.OkButtonLabel = "Schließen"; a.Invoke(); return; } } if (CanFormat(null)) { SettingsRepository repository = SettingsRepository.Load(); Guid lastSettingsUid = Properties.Settings.Default.LastSettings; Settings lastSettings = repository.FindByGuid(lastSettingsUid); if (lastSettings != null) { DoFormat(lastSettings); } else { DoChooseSettings(); } } } void DoFormat(Settings settings) { ZaaImporter importer = new ZaaImporter(); importer.Import(Globals.ThisAddIn.Application.ActiveWindow.Selection.Text); Formatter.Formatter formatter = new Formatter.Formatter( Globals.ThisAddIn.Application.ActiveDocument); formatter.Settings = settings; formatter.Laboratory = importer.Laboratory; try { formatter.Run(); } catch (NoLaboratoryDataException) { NotificationAction a = new NotificationAction(); a.Caption = "Formatieren nicht möglich"; a.Message = "Die aktuelle Markierung scheint keine Labordaten zu enthalten."; a.OkButtonLabel = "Schließen"; a.Invoke(); } } void DoChooseSettings() { SettingsRepository repository = SettingsRepository.Load(); SettingsRepositoryViewModel vm = new SettingsRepositoryViewModel(repository); vm.UseSettingsMessage.Sent += (sender, args) => { SettingsViewModel settingsVM = args.Content.ViewModel as SettingsViewModel; Settings settings = settingsVM.RevealModelObject() as Settings; DoFormat(settings); Properties.Settings.Default.LastSettings = settings.Uid; Properties.Settings.Default.Save(); }; vm.InjectInto().ShowDialog(); } /// /// Loads the embedded demo document. /// /// /// If Word is running in an embedded environment (e.g. in the ZAA), /// adding a document causes a COMException. Unfortunately, it is /// not trivial to test if Word is running embedded, so we use a /// try...catch structure and catch all COMExceptions. The error /// message might be not quite right if the exception was caused by /// a different problem. /// See http://davecra.com/2013/04/10/how-to-determine-if-an-excel-workbook-is-embedded-and-more /// void DoLoadDemo() { try { Demo.Demo.OpenDemoDocument(); } catch (System.Runtime.InteropServices.COMException e) { // HRESULT comparison according to http://stackoverflow.com/a/1426198/270712 // Fix for exception ID 65a5c34e if (e.ErrorCode == unchecked((int)0x800A11FD)) { NotificationAction a = new NotificationAction(); a.Caption = "Kann Demo-Dokument nicht laden"; a.Message = "Das Demo-Dokument kann nicht geladen werden, " + "wenn Word in der Zentralen Arztbriefablage ausgeführt wird.\r" + "Bitte Word als eigenständige Anwendung starten und dann " + "noch einmal versuchen."; a.OkButtonLabel = "Schließen"; a.Invoke(); } else { throw; } } } public void Application_WindowSelectionChange(Microsoft.Office.Interop.Word.Selection Sel) { _ribbon.Invalidate(); } #endregion #region Helpers private static string GetResourceText(string resourceName) { Assembly asm = Assembly.GetExecutingAssembly(); string[] resourceNames = asm.GetManifestResourceNames(); for (int i = 0; i < resourceNames.Length; ++i) { if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0) { using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i]))) { if (resourceReader != null) { return resourceReader.ReadToEnd(); } } } } return null; } #endregion #region Fields private Office.IRibbonUI _ribbon; #endregion } }