Development Docs - accessibilitysoftwarehub/iconBasedCommunicator GitHub Wiki


DEVELOPMENT DOCUMENTATION


IMAGES


Resizing icons/images for project


  • Open Adobe Photoshop
  • If Actions Window is not open, press Alt+F9 to do so
  • Click the Menu Icon on the Action Window and select Load Actions...
  • Navigate to project repository on your local computer and open iconBasedCommunicator->PhotoshopActions and load Icon.atn
  • Select File->Automate->Batch...
  • Under Source: Folder, click choose... and select the folder of images you wish to resize
  • Leave Include All Subfolders unchecked
  • Ensure Override Action "Save As" Commands is ticked
  • Click OK to start resizing

Image Binding:


  • Add this new key path property to the key class. (key.cs)

          public static readonly DependencyProperty IconImageProperty =
          DependencyProperty.Register("IconImage", typeof(BitmapImage), typeof(Key),
          new PropertyMetadata(default(string), OnIconImageOrTextChanged));
    
          public BitmapImage IconImage
          {
              get { return (BitmapImage)GetValue(IconImageProperty); }
              set { SetValue(IconImageProperty, value); }
          }
    
          private static void OnIconImageOrTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs      e)
          {
              var senderAsKey = sender as Key;
              if (senderAsKey != null && senderAsKey.PropertyChanged != null)
              {
                  senderAsKey.OnPropertyChanged("HasImage");
                  senderAsKey.OnPropertyChanged("HasText");
              }
          }
    
          public bool HasImage { get { return IconImage != null; } }
    
  • Modify the theme so the key template includes an image bound to a new image path property on the key class. (Android_Dark.xaml)

          <!-- This is the template for an individual Key. The actual components are down at the bottom, you'll see   Text and Path already.
          we need to add an Image -->           
          <Style TargetType="{x:Type controls:Key}">
              <Setter Property="Template">
                                  ...
    
           <TextBlock Style="{StaticResource KeyTextStyle}" />
           <Path Style="{StaticResource KeySymbolStyle}" Width="64" Height="64" VerticalAlignment="Center" />
    
         <Style x:Key ="KeyImageStyle" TargetType="Image">
            <Setter Property="Source" Value="{Binding Path=IconImage, RelativeSource={RelativeSource AncestorType={x:Type controls:Key}}, Mode=OneWay}"/>

            <Style.Triggers>
               
                <!--Is there an IconImage to display-->
                <!-- If this key instance's HasImage property = true (see Key.cs for event handlers -->
                <!-- then this element is visible. If HasImage is false, it's not. This sort of beats up -->
                <!-- the styling of the symbols and text, but I think that's buried in the other styles.-->
               
                <DataTrigger Binding="{Binding Path=HasImage, RelativeSource={RelativeSource AncestorType={x:Type controls:Key}}, Mode=OneWay}" Value="True">
                    <Setter Property="Visibility" Value="Visible" />
                </DataTrigger>

                <DataTrigger Binding="{Binding Path=HasImage, RelativeSource={RelativeSource AncestorType={x:Type controls:Key}}, Mode=OneWay}" Value="False">
                    <Setter Property="Visibility" Value="Hidden" />
                </DataTrigger>

            </Style.Triggers>

            </Style>

Adding icons/images to project


(Have only tested with pngs)

  • Right click image folder of choice (SVG Source Files)
  • Add -> Existing Item
  • Click on added image in folder
  • In properties window
    -> Change [Build Action] to [Content]
    -> Change [Copy to Output Directory] to [Copy Always]

Binding icons/images to keyboard grid


  • Add key to Resources/Icons/KeySymbols.xaml
    ->Example

       <BitmapImage x:Key="HappyIcon" UriSource="/Resources/Icons/SVG Source Files/happy.png"/>  
    
  • In keyboard of choice (Alpha.xaml for top layer)
    ->Example in KEYBOARD KEYS section

       <controls:Key Grid.Row="2" Grid.Column="3" Grid.ColumnSpan="2"  
                     IconImage="{StaticResource HappyIcon}"  
                     Text="Happy"  ````
                     SharedSizeGroup="KeyWithSymbol"
                     Value="Happy"/> 
    

KEYBOARD VIEWS


Creating new keyboard


  • Open Blend
  • Open IconKeyboardTemplate.xaml
  • Copy all content
  • Right click the folder that will contain new keyboard (View/Keyboards)
  • Add -> UserControl
  • Remove all code from newly created xaml file
  • Replace with code copied from KeyboardTemplate.xaml

<controls:KeyboardView x:Class="OptiKey.UI.Views.Keyboards.Common.KeyboardTemplate" -> alter .KeyboardTemplate to whatever you named your new xaml file

  • Save then exit blend
  • In Enums/FunctionKeys.cs add "[keyboardname]Keyboard" to list
  • In Enums/Keyboards.cs add "[keyboardname]Keyboard" to list
  • In Models/KeyValues add:

public static readonly KeyValue [keyboardname]KeybaordKey = new KeyValue(FunctionKeys.[keyboardname]Keyboard);

  • In UI/ViewModels/Keyboards/Common add new class "[keyboardname].cs"

  • Replicate the other keyboard files in this folder making sure the correct import is used, Keyboard is inherited and the class is public

  • Adjust [keyboardname].xaml so the x:Class="OptiKey.UI.Views.Keyboards.Common.TestKeyboard" path is correct "At top of file"

  • Adjust [keyboardname].xaml.cs so that the import is correct, the class is public and it inherits KeyboardView correctly.

  • In UI/Controls/KeyboardHost.cs add:

        else if(Keyboard is ViewModelKeyboards.[keyboardname])  
             {  
                 newContent = new CommonViews.[keyboardname] { DataContext = Keyboard };  
             }  
    
  • In ViewModels/Management/MainViewModel.cs add case statement to InitialiseKeyboard method:

        case Enums.Keyboards.[keyboardname]:  
              Keyboard = new [keyboardname]();  
              windowManipulationService.Restore();  
              mainWindowManipulationService.ResizeDockToFull();  
              break;
    
  • In MainViewModel.ServiceEventHandlers.cs add case statement to HandleFunctionKeySelectionResult method:

        case FunctionKeys.[keyboardname]Keyboard:  
             Log.Info("Changing keyboard to PhysicalKeys.");  
             Keyboard = new [keyboardname]();  
             break;
    

Calling keyboard from keyboard key


  • Open relevant keybaord (Alpha.xaml)
    ->Example in KEYBOARD KEYS section

         <controls:Key Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2"  
                       IconImage="{StaticResource FoodIcon}"  
                       Text="Food"  
                       SharedSizeGroup="KeyWithSymbol"  
                       Value="{x:Static models:KeyValues.FoodKeyboardKey}"/> 
    

LANGUAGES


Adding a Language

(Icons example)


  • Added a folder in the project heirachy - UI/Views/Keyboards/[Iconic]
  • Created a new alpha keyboard in the Iconic folder (alpha.xaml - copied alpha from English folder and adjusted)
  • Adjusted top line of alpha.xaml
  • From controls:KeyboardView x:Class="OptiKey.UI.Views.Keyboards.English.Alpha"
  • To controls:KeyboardView x:Class="OptiKey.UI.Views.Keyboards.Iconic.Alpha"
<controls:KeyboardView x:Class="OptiKey.UI.Views.Keyboards.Iconic.Alpha"
                       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:controls="clr-namespace:OptiKey.UI.Controls"
                       xmlns:models="clr-namespace:OptiKey.Models"
                       xmlns:resx="clr-namespace:OptiKey.Properties"
                       mc:Ignorable="d" 
                       d:DesignHeight="300" d:DesignWidth="300">

  • Created a new Output with scratchpad specifically for the iconic keyboard at UI/Controls/
  • Modified the existing output.xaml file by copying and altering
/// <summary>
    /// IconOutput
    /// </summary>
    public partial class IconOutput : System.Windows.Controls.UserControl, System.Windows.Markup.IComponentConnector {
  • Adjusted the layout of the IconOutput.xaml
  • Added the new icon output to the iconic aplha.xaml
 <!-- will need to revert row span back to 2 when reverting whole keyboard-->
        <controls:IconOutput Grid.Row="1" Grid.Column="1"
                         Grid.RowSpan="1" Grid.ColumnSpan="24" 
                         ScratchpadWidthInKeys="7"
                         NumberOfSuggestionsDisplayed="{Binding Path=DataContext.SuggestionService.SuggestionsPerPage, RelativeSource={RelativeSource AncestorType=controls:KeyboardHost}, Mode=TwoWay}" />
        <!--N.B. This MUST be TwoWay to detect changes to the DataContext used in the binding path-->
  • Added IconsIconic to FunctionKeys.cs enum (Enums/FunctionKeys)
  • Added IconsIconic to Languages.cs enum and EnumExtensions and in the Languages.cs file (Enums/Languages.cs)
public static partial class EnumExtensions
    {
        public static string ToDescription(this Languages languages)
        {
            switch (languages)
            {
                case Languages.DutchBelgium: return Resources.DUTCH_BELGIUM;
                case Languages.DutchNetherlands: return Resources.DUTCH_NETHERLANDS;
                case Languages.EnglishCanada: return Resources.ENGLISH_CANADA;
                case Languages.EnglishUK: return Resources.ENGLISH_UK;
                case Languages.EnglishUS: return Resources.ENGLISH_US;
                case Languages.FrenchFrance: return Resources.FRENCH_FRANCE;
                case Languages.GermanGermany: return Resources.GERMAN_GERMANY;
                case Languages.IconsIconic: return Resources.ICONS_ICONIC;
                case Languages.RussianRussia: return Resources.RUSSIAN_RUSSIA;
                case Languages.SpanishSpain: return Resources.SPANISH_SPAIN;
            }

            return languages.ToString();
        }
public static CultureInfo ToCultureInfo(this Languages languages)
        {
            switch (languages)
            {
                case Languages.DutchBelgium: return CultureInfo.GetCultureInfo("nl-BE");
                case Languages.DutchNetherlands: return CultureInfo.GetCultureInfo("nl-NL");			
                case Languages.EnglishUS: return CultureInfo.GetCultureInfo("en-US");
                case Languages.EnglishUK: return CultureInfo.GetCultureInfo("en-GB");
                case Languages.EnglishCanada: return CultureInfo.GetCultureInfo("en-CA");
                case Languages.FrenchFrance: return CultureInfo.GetCultureInfo("fr-FR");
                case Languages.GermanGermany: return CultureInfo.GetCultureInfo("de-DE");
                case Languages.IconsIconic: return CultureInfo.GetCultureInfo("en-US");
                case Languages.RussianRussia: return CultureInfo.GetCultureInfo("ru-RU");
                case Languages.SpanishSpain: return CultureInfo.GetCultureInfo("es-ES");
            }

            return CultureInfo.GetCultureInfo("en-GB");
        }
  • Added property to the KeyValues.cs to link the Key with the FunctionKey
public static readonly KeyValue IconsIconicKey = new KeyValue(FunctionKeys.IconsIconic);
  • Also added the Language tot the KeyValue construstor in the same code file (KeyValue.cs)
static KeyValues()
        {
            var defaultList = "abcdefghijklmnopqrstuvwxyz"
                .ToCharArray()
                .Select(c => new KeyValue(c.ToString(CultureInfo.InvariantCulture)))
                .ToList();

            multiKeySelectionKeys = new Dictionary<Languages, List<KeyValue>>
            {
                { Languages.DutchBelgium, defaultList },
                { Languages.DutchNetherlands, defaultList },
                { Languages.EnglishCanada, defaultList },
                { Languages.EnglishUK, defaultList },
                { Languages.EnglishUS, defaultList },
                { Languages.IconsIconic, defaultList },
                { Languages.SpanishSpain, defaultList },
                { Languages.FrenchFrance, defaultList }, //Could be customised to include àçéèù
                { Languages.GermanGermany, defaultList }, //Could be customised to include äöüß
				{ Languages.RussianRussia, "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
                                                .ToCharArray()
                                                .Select(c => new KeyValue (c.ToString(CultureInfo.InvariantCulture) ))
                                                .ToList() }
            };
        }
  • Added following code to Language.xaml in UI/Views/Keyboards/Common/Language.xaml
<controls:Key Grid.Row="3" Grid.Column="0"
                                          Text="{x:Static resx:Resources.ICONS_ICONIC}"
                                          SharedSizeGroup="KeyWithText"
                                          Value="{x:Static models:KeyValues.IconsIconicKey}"/>
  • Added a string resource to the project by going to Project -> [Projectname] Properties -> Resources Tab -> Add Resources. Added ICONS_ICONIC as Icons (Cognitive and Motor Impairment). This string will now show up on the languages view when run.
⚠️ **GitHub.com Fallback** ⚠️