Skip to content

Instantly share code, notes, and snippets.

@iseebi
Created July 26, 2010 17:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iseebi/490882 to your computer and use it in GitHub Desktop.
Save iseebi/490882 to your computer and use it in GitHub Desktop.
Japanese IME on Windows Phone 7 powered by Social IME
<phone:PhoneApplicationPage
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:System="clr-namespace:System;assembly=mscorlib"
x:Class="AjaxIMETest.MainPage"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
shell:SystemTray.IsVisible="True">
<phone:PhoneApplicationPage.Resources>
<ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
</ItemsPanelTemplate>
<DataTemplate x:Key="DataTemplate1">
<Grid>
<TextBlock Margin="0,0,6,7" TextWrapping="Wrap" Text="{Binding}" d:LayoutOverrides="Width, Height" Foreground="{StaticResource PhoneForegroundBrush}"/>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<!-- Sample code showing usage of ApplicationBar
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
<shell:ApplicationBarIconButton x:Name="appbar_button1" IconUri="/Images/appbar_button1.png" Text="Button 1"></shell:ApplicationBarIconButton>
<shell:ApplicationBarIconButton x:Name="appbar_button2" IconUri="/Images/appbar_button2.png" Text="Button 2"></shell:ApplicationBarIconButton>
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem x:Name="menuItem1" Text="MenuItem 1"></shell:ApplicationBarMenuItem>
<shell:ApplicationBarMenuItem x:Name="menuItem2" Text="MenuItem 2"></shell:ApplicationBarMenuItem>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
-->
<phone:PhoneApplicationPage.FontFamily>
<StaticResource ResourceKey="PhoneFontFamilyNormal"/>
</phone:PhoneApplicationPage.FontFamily>
<phone:PhoneApplicationPage.FontSize>
<StaticResource ResourceKey="PhoneFontSizeNormal"/>
</phone:PhoneApplicationPage.FontSize>
<phone:PhoneApplicationPage.Foreground>
<StaticResource ResourceKey="PhoneForegroundBrush"/>
</phone:PhoneApplicationPage.Foreground>
<!--LayoutRoot contains the root grid where all other page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentGrid" Grid.Row="1">
<TextBox Height="73" HorizontalAlignment="Left" Margin="0,6,0,0" x:Name="textBox1" Text="" VerticalAlignment="Top" Width="313" d:IsLocked="True" KeyDown="textBox1_KeyDown" />
<Button Content="IME Off" Height="72" HorizontalAlignment="Right" Margin="0,7,6,0" x:Name="button1" VerticalAlignment="Top" Width="155" Click="button1_Click" Background="#FFEB3030" d:IsLocked="True" />
<Grid Margin="0,8,8,0" x:Name="conjectureGrid" VerticalAlignment="Top" HorizontalAlignment="Right" Height="171">
<Rectangle VerticalAlignment="Top" Stroke="{StaticResource PhoneAccentBrush}" Fill="{StaticResource PhoneBackgroundBrush}"/>
<TextBox x:Name="textBox2" Text="" TextChanged="textBox2_TextChanged" Height="73" VerticalAlignment="Top" HorizontalAlignment="Left" Width="464" Margin="0,2,0,0" KeyUp="textBox2_KeyUp" />
<ListBox HorizontalAlignment="Left" Margin="0,63,0,0" x:Name="listBox1" Width="464" ItemsPanel="{StaticResource ItemsPanelTemplate1}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
FontSize="29.333" Grid.Column="0" d:LayoutOverrides="GridBox" Height="73" VerticalAlignment="Top" SelectionChanged="listBox1_SelectionChanged" ItemTemplate="{StaticResource DataTemplate1}" />
<TextBlock Height="21" TextWrapping="Wrap" Text="powered by SocialIME" VerticalAlignment="Bottom" TextAlignment="Right" Margin="150,0,4,9" FontSize="16" Foreground="{StaticResource PhoneAccentBrush}"/>
</Grid>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Text.RegularExpressions;
namespace AjaxIMETest
{
public partial class MainPage : PhoneApplicationPage
{
bool m_imeStatus = false;
WebClient m_client;
Dictionary<string, string> m_romajiToKanaTable = new Dictionary<string, string>()
{
{".","。"},{",","、"},{"-","ー"},{"~","?"},{"?","?"},{"!","!"},{"va","ヴぁ"},{"vi","ヴぃ"},{"vu","ヴ"},{"ve","ヴぇ"},{"vo","ヴぉ"},{"vv", "っ"},{"xx", "っ"},{"kk", "っ"},{"gg", "っ"},{"ss", "っ"},{"zz", "っ"},
{"jj", "っ"},{"tt", "っ"},{"dd", "っ"},{ "hh", "っ"},{"ff", "っ"},{"bb","っ"},{"pp", "っ"},{"mm","っ"},{"yy", "っ"},{"rr","っ"},{"ww", "っ"},{"cc", "っ"},{"kya","きゃ"},{"kyi","きぃ"},
{"kyu","きゅ"},{"kye","きぇ"},{"kyo","きょ"},{"gya","ぎゃ"},{"gyi","ぎぃ"},{"gyu","ぎゅ"},{"gye","ぎぇ"},{"gyo","ぎょ"},{"sya","しゃ"},{"syi","しぃ"},{"syu","しゅ"},{"sye","しぇ"},{"syo","しょ"},
{"sha","しゃ"},{"shi","し"},{"shu","しゅ"},{"she","しぇ"},{"sho","しょ"},{"zya","じゃ"},{"zyi","じぃ"},{"zyu","じゅ"},{"zye","じぇ"},{"zyo","じょ"},{"tya","ちゃ"},{"tyi","ちぃ"},{"tyu","ちゅ"},
{"tye","ちぇ"},{"tyo","ちょ"},{"cha","ちゃ"},{"chi","ち"},{"chu","ちゅ"},{"che","ちぇ"},{"cho","ちょ"},{"dya","ぢゃ"},{"dyi","ぢぃ"},{"dyu","ぢゅ"},{"dye","ぢぇ"},{"dyo","ぢょ"},{"tha","てゃ"},
{"thi","てぃ"},{"thu","てゅ"},{"the","てぇ"},{"tho","てょ"},{"dha","でゃ"},{"dhi","でぃ"},{"dhu","でゅ"},{"dhe","でぇ"},{"dho","でょ"},{"nya","にゃ"},{"nyi","にぃ"},{"nyu","にゅ"},{"nye","にぇ"},
{"nyo","にょ"},{"jya","じゃ"},{"jyi","じ"},{"jyu","じゅ"},{"jye","じぇ"},{"jyo","じょ"},{"hya","ひゃ"},{"hyi","ひぃ"},{"hyu","ひゅ"},{"hye","ひぇ"},{"hyo","ひょ"},{"bya","びゃ"},{"byi","びぃ"},
{"byu","びゅ"},{"bye","びぇ"},{"byo","びょ"},{"pya","ぴゃ"},{"pyi","ぴぃ"},{"pyu","ぴゅ"},{"pye","ぴぇ"},{"pyo","ぴょ"},{"fa","ふぁ"},{"fi","ふぃ"},{"fe","ふぇ"},{"fo","ふぉ"},{"mya","みゃ"},
{"myi","みぃ"},{"myu","みゅ"},{"mye","みぇ"},{"myo","みょ"},{"rya","りゃ"},{"ryi","りぃ"},{"ryu","りゅ"},{"rye","りぇ"},{"ryo","りょ"},{"n\"","ん"},{"nn","ん"},{"a","あ"},{"i","い"},{"u","う"},
{"e","え"},{"o","お"},{"xa","ぁ"},{"xi","ぃ"},{"xu","ぅ"},{"xe","ぇ"},{"xo","ぉ"},{"la","ぁ"},{"li","ぃ"},{"lu","ぅ"},{"le","ぇ"},{"lo","ぉ"},{"ka","か"},{"ki","き"},{"ku","く"},{"ke","け"},{"ko","こ"},
{"ga","が"},{"gi","ぎ"},{"gu","ぐ"},{"ge","げ"},{"go","ご"},{"sa","さ"},{"si","し"},{"su","す"},{"se","せ"},{"so","そ"},{"za","ざ"},{"zi","じ"},{"zu","ず"},{"ze","ぜ"},{"zo","ぞ"},{"ja","じゃ"},{"ji","じ"},
{"ju","じゅ"},{"je","じぇ"},{"jo","じょ"},{"ta","た"},{"ti","ち"},{"tu","つ"},{"tsu","つ"},{"te","て"},{"to","と"},{"da","だ"},{"di","ぢ"},{"du","づ"},{"de","で"},{"do","ど"},{"xtu","っ"},{"xtsu","っ"},
{"na","な"},{"ni","に"},{"nu","ぬ"},{"ne","ね"},{"no","の"},{"ha","は"},{"hi","ひ"},{"hu","ふ"},/*{"fu","ふ"},*/{"he","へ"},{"ho","ほ"},{"ba","ば"},{"bi","び"},{"bu","ぶ"},{"be","べ"},{"bo","ぼ"},{"pa","ぱ"},
{"pi","ぴ"},{"pu","ぷ"},{"pe","ぺ"},{"po","ぽ"},{"ma","ま"},{"mi","み"},{"mu","む"},{"me","め"},{"mo","も"},{"xya","ゃ"},{"ya","や"},{"xyu","ゅ"},{"yu","ゆ"},{"xyo","ょ"},{"yo","よ"},{"ra","ら"},{"ri","り"},
{"ru","る"},{"re","れ"},{"ro","ろ"},{"xwa","ゎ"},{"wa","わ"},{"wi","うぃ"},{"we","うぇ"},{"wo","を"}
};
// Constructor
public MainPage()
{
InitializeComponent();
m_client = new WebClient();
m_client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(m_client_DownloadStringCompleted);
CloseConjecture();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
m_imeStatus = !m_imeStatus;
if (m_imeStatus)
{
button1.Content = "IME On";
button1.Background = Application.Current.Resources["PhoneAccentBrush"] as Brush;
}
else
{
button1.Content = "IME Off";
button1.Background = Application.Current.Resources["PhoneBackgroundBrush"] as Brush;
CloseConjecture();
}
textBox1.Focus();
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (m_imeStatus)
{
char chr = keyToChar(e.Key);
if (chr != '\0')
{
e.Handled = true;
OpenConjecture(chr.ToString());
}
}
}
private void OpenConjecture(string defaultStr)
{
textBox2.Text = defaultStr.ToLower();
textBox2.SelectionStart = textBox2.Text.Length;
listBox1.ItemsSource = null;
conjectureGrid.Visibility = System.Windows.Visibility.Visible;
textBox2.Focus();
}
private void CloseConjecture()
{
conjectureGrid.Visibility = System.Windows.Visibility.Collapsed;
}
private void decideToText(string text)
{
textBox1.SelectedText = text;
CloseConjecture();
textBox1.Focus();
}
private void textBox2_TextChanged(object sender, TextChangedEventArgs e)
{
// キャレット位置までの文字列を得る
string text_all = textBox2.Text;
string text1 = text_all.Substring(0, textBox2.SelectionStart);
// 末尾までのアルファベットを取得
Match m = Regex.Match(text1, "[a-zA-Z_0-9,.!?-]+$");
if (m.Success)
{
if (m_romajiToKanaTable.ContainsKey(m.Value))
{
// 当該範囲置換
textBox2.Text = text_all.Substring(0, m.Index)
+ m_romajiToKanaTable[m.Value]
+ text_all.Substring(text1.Length);
// キャレット位置設定
textBox2.SelectionStart = m.Index + m_romajiToKanaTable[m.Value].Length;
// Socal IME へリクエスト
m_client.DownloadStringAsync(new Uri("http://www.social-ime.com/api2/predict.php?string=" + Uri.EscapeDataString(textBox2.Text)));
}
}
}
void m_client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
listBox1.ItemsSource = e.Result.Split(new char[] {'\t'}, StringSplitOptions.RemoveEmptyEntries);
}
private void textBox2_KeyUp(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Back:
if (textBox2.Text == String.Empty)
{
CloseConjecture();
}
break;
case Key.Enter:
decideToText(textBox2.Text);
break;
}
}
private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0)
{
decideToText(e.AddedItems[0] as string);
}
}
private char keyToChar(Key key)
{
switch (key)
{
case Key.A: return 'A';
case Key.Add: return '+';
case Key.B: return 'B';
case Key.C: return 'C';
case Key.D:return 'D';
case Key.D0:return '0';
case Key.D1:return '1';
case Key.D2:return '2';
case Key.D3:return '3';
case Key.D4:return '4';
case Key.D5:return '5';
case Key.D6:return '6';
case Key.D7:return '7';
case Key.D8:return '8';
case Key.D9:return '9';
case Key.Divide:return '/';
case Key.E:return 'E';
case Key.Enter:return '\n';
case Key.F:return 'F';
case Key.G:return 'G';
case Key.H:return 'H';
case Key.I:return 'I';
case Key.J:return 'J';
case Key.K:return 'K';
case Key.L:return 'L';
case Key.M:return 'M';
case Key.Multiply:return '*';
case Key.N:return 'N';
case Key.NumPad0:return '0';
case Key.NumPad1:return '1';
case Key.NumPad2:return '2';
case Key.NumPad3:return '3';
case Key.NumPad4:return '4';
case Key.NumPad5:return '5';
case Key.NumPad6:return '6';
case Key.NumPad7:return '7';
case Key.NumPad8:return '8';
case Key.NumPad9:return '9';
case Key.O:return 'O';
case Key.P:return 'P';
case Key.Q:return 'Q';
case Key.R:return 'R';
case Key.S:return 'S';
case Key.Space:return ' ';
case Key.Subtract:return '-';
case Key.T:return 'T';
case Key.Tab:return '\t';
case Key.U:return 'U';
case Key.V:return 'V';
case Key.W:return 'W';
case Key.X:return 'X';
case Key.Y:return 'Y';
case Key.Z:return 'Z';
default:
return '\0';
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment