vitorsousa pushed a commit to branch master. http://git.enlightenment.org/tools/examples.git/commit/?id=6009c1046cb77de93c5bcd524e73897d4dbcfa33
commit 6009c1046cb77de93c5bcd524e73897d4dbcfa33 Author: Vitor Sousa <vitorsousasi...@gmail.com> Date: Thu Feb 22 14:44:55 2018 -0300 apps_mono: add text editor and Game of Life example apps for C# binding --- apps/csharp/life/meson.build | 10 ++ apps/csharp/life/src/life_board.cs | 163 ++++++++++++++++++++++++++ apps/csharp/life/src/life_main.cs | 83 +++++++++++++ apps/csharp/life/src/life_render.cs | 71 +++++++++++ apps/csharp/life/src/meson.build | 14 +++ apps/csharp/texteditor/meson.build | 10 ++ apps/csharp/texteditor/src/meson.build | 12 ++ apps/csharp/texteditor/src/texteditor_main.cs | 143 ++++++++++++++++++++++ 8 files changed, 506 insertions(+) diff --git a/apps/csharp/life/meson.build b/apps/csharp/life/meson.build new file mode 100644 index 0000000..bb46815 --- /dev/null +++ b/apps/csharp/life/meson.build @@ -0,0 +1,10 @@ +project( + 'efl-example-life', 'cs', + version : '0.0.1', + meson_version : '>= 0.38.0') + +efl_mono = dependency('efl-mono', version : '>=1.20.99') +efl_mono_libs = efl_mono.get_pkgconfig_variable('mono_libs') + +subdir('src') + diff --git a/apps/csharp/life/src/life_board.cs b/apps/csharp/life/src/life_board.cs new file mode 100644 index 0000000..ca12115 --- /dev/null +++ b/apps/csharp/life/src/life_board.cs @@ -0,0 +1,163 @@ +using System; + +public class LifeBoard +{ + public const int Width = 47; + public const int Height = 31; + + public static int IndexForPosition(int x, int y) + { + return y * Width + x; + } + + public bool[] Cells + { + get { return board; } + } + + private int gen = 0; + + private bool[] board, boardPrev; + private bool[] board1, board2; + private efl.loop.Timer lifeTimer = null; + private LifeRender lifeRender = null; + + private void CellOn(int x, int y) + { + board1[IndexForPosition(x, y)] = true; + } + + private void BoardSetup() + { + // glide + CellOn(16, 1); + CellOn(17, 2); + CellOn(18, 2); + CellOn(16, 3); + CellOn(17, 3); + + // oscilate + CellOn(22, 15); + CellOn(23, 15); + CellOn(24, 15); + + // block + CellOn(32, 15); + CellOn(33, 15); + CellOn(32, 16); + CellOn(33, 16); + } + + public LifeBoard() + { + board1 = new bool[Height * Width]; + board2 = new bool[Height * Width]; + + BoardSetup(); + + board = board1; + boardPrev = board2; + } + + public void Run(efl.ui.Win win) + { + lifeTimer = new efl.loop.Timer(null, (efl.loop.Timer etimer) => { + etimer.SetInterval(0.1); + }); + + lifeTimer.TICK += (object sender, EventArgs ev) => { + Nextgen(); + if (this.lifeRender != null) + this.lifeRender.Refresh(win); + }; + } + + public int SumAround(int x, int y) + { + int i, sum = 0; + int max = Width * Height; + + i = IndexForPosition(x - 1, (y - 1)); + if (i >= 0 && board[i]) + ++sum; + ++i; + if (i >= 0 && board[i]) + ++sum; + ++i; + if (i >= 0 && board[i]) + ++sum; + + i = IndexForPosition(x - 1, y); + if (i >= 0 && board[i]) + ++sum; + i += 2; + if (i < max && board[i]) + ++sum; + + i = IndexForPosition(x - 1, (y + 1)); + if (i < max && board[i]) + ++sum; + ++i; + if (i < max && board[i]) + ++sum; + ++i; + if (i < max && board[i]) + ++sum; + + return sum; + } + + public void Nextgen() + { + int[] work = null; + ++gen; + + if (board == board1) + work = board2; + else + work = board1; + + for (int y = 0; y < LIFE_BOARD_HEIGHT; y++) + for (int x = 0; x < LIFE_BOARD_WIDTH; x++) + { + int i = IndexForPosition(x, y); + + int n = SumAround(x, y); + if (board[i]) + { + if (n > 3 || n < 2) + work[i] = false; + else + work[i] = true; + } + else + { + if (n == 3) + work[i] = true; + else + work[i] = false; + } + } + + boardPrev = board; + board = work; + } + + public void TogglePause(efl.ui.Win win) + { + if (lifeTimer) + { + lifeTimer.Dispose(); + lifeTimer = null; + } + else + { + Run(win); + } + } + + public void SetRender(LifeRender render) + { + lifeRender = render; + } +} diff --git a/apps/csharp/life/src/life_main.cs b/apps/csharp/life/src/life_main.cs new file mode 100644 index 0000000..9b9ce35 --- /dev/null +++ b/apps/csharp/life/src/life_main.cs @@ -0,0 +1,83 @@ +using System; + +public class LifeWindow +{ + private LifeBoard lifeBoard; + private LifeRender lifeRender; + + void ResizeEvt(efl.ui.Win win, EventArgs ev) + { + lifeRender.Layout(win); + } + + void QuitEvt(efl.ui.Win win, EventArgs ev) + { + // quit the mainloop + efl.ui.Config.Exit(); + } + + void TouchEvt(efl.ui.Win win, efl.input.Pointer ev) + { + int cellx, celly; + var position = ev.GetPosition(); + lifeRender.CellForCoords(win, position, out cellx, out celly); + + int i = LifeRender.IndexForPosition(cellx, celly); + lifeBoard.Cells[i] = !lifeBoard.Cells[i]; + lifeRender.RenderCell(win, cellx, celly); + } + + void KeyDownEvt(efl.ui.Win win, efl.input.Key ev) + { + if (ev.GetKey() == "space") + lifeBoard.TogglePause(win); + } + + public void Run() + { + lifeBoard.Run(win); + } + + public LifeWindow() + { + efl.ui.Win win = new efl.Ui.WinConcrete(null, (efl.ui.Win ewin) => { + ewin.SetWinType(efl.ui.win.Type.Basic); + ewin.SetText("EFL Life"); + ewin.SetAutohide(true); + }); + + // when the user clicks "close" on a window there is a request to hide + win.HIDE += QuitEvt; + + eina.Size2D sz; + sz.W = 10 * LifeBoard.Width * win.GetScale(); + sz.H = 10 * LifeBoard.Height * win.GetScale(); + + lifeBoard = new LifeBoard(); + lifeRender = new LifeRender(win, lifeBoard); + lifeRender.Refresh(win); + + win.RESIZE += ResizeEvt; + win.POINTER_DOWN += TouchEvt; + win.KEY_DOWN += KeyDownEvt; + + win.SetSize(sz); + } +} + +public class Example +{ + public static void Main() + { + efl.All.Init(efl.Components.Ui); + + var lifeWin = new LifeWin(); + + lifeWin.Run(); + + // start the mainloop + efl.ui.Config.Run(); + + efl.All.Shutdown(); + } +} diff --git a/apps/csharp/life/src/life_render.cs b/apps/csharp/life/src/life_render.cs new file mode 100644 index 0000000..0b5348a --- /dev/null +++ b/apps/csharp/life/src/life_render.cs @@ -0,0 +1,71 @@ +using System; + +public class LifeRender +{ + private efl.canvas.Rectangle[] lifeCells; + private LifeBoard lifeBoard; + + public LifeRender(efl.ui.Win win, LifeBoard board) + { + lifeBoard = board; + lifeBoard.SetRender(this); + + lifeCells = new efl.canvas.Rectangle[LifeBoard.Height * LifeBoard.Width]; + + for (int y = 0; y < LifeBoard.Height; ++y) + for (int x = 0; x < LifeBoard.Width; ++x) + lifeCells[LifeBoard.IndexForPosition(x, y)] = new efl.canvas.RectangleConcrete(win); + + RenderLayout(win); + } + + public void CellForCoords(efl.ui.Win win, eina.Position2D coord, out int x, out int y) + { + eina.Size2D size = win.GetSize(); + + x = coord.X / ((double) size.W / LifeBoard.Width); + y = coord.Y / ((double) size.H / LifeBoard.Height); + } + + public void RenderLayout(efl.ui.Win win) + { + eina.Size2D size = win.GetSize(); + double cw = (double) size.W / LifeBoard.Width; + double ch = (double) size.H / LifeBoard.Height; + + for (int y = 0; y < LifeBoard.Height; ++y) + for (int x = 0; x < LifeBoard.Width; ++x) + { + var rect = lifeCells[LifeBoard.IndexForPosition(x, y)]; + + // the little +1 here will avoid tearing as we layout non-multiple sizes + eina.Size2D sz; + sz.W = cw + 1; + sz.H = ch + 1; + rect.SetSize(sz); + + eina.Position2D pos; + pos.X = x * cw; + pos.Y = y * ch; + rect.SetPosition(pos); + } + } + + public void RenderCell(efl.ui.Win win, int x, int y) + { + int i = LifeBoard.IndexForPosition(x, y); + var rect = lifeCells[i]; + + if (lifeBoard.Cells[i]) + rect.SetColor(0, 0, 0, 255); + else + rect.SetColor(255, 255, 255, 255); + } + + public void Refresh(efl.ui.Win win) + { + for (int y = 0; y < LifeBoard.Height; ++y) + for (int x = 0; x < LifeBoard.Width; ++x) + RenderCell(win, x, y); + } +} diff --git a/apps/csharp/life/src/meson.build b/apps/csharp/life/src/meson.build new file mode 100644 index 0000000..88ff384 --- /dev/null +++ b/apps/csharp/life/src/meson.build @@ -0,0 +1,14 @@ +src = files([ + 'life_render.cs', + 'life_board.cs', + 'life_main.cs', +]) + +deps = [efl_mono] + +executable('efl_example_life', src, + dependencies : deps, + cs_args : efl_mono_libs, + install : true +) + diff --git a/apps/csharp/texteditor/meson.build b/apps/csharp/texteditor/meson.build new file mode 100644 index 0000000..5aacda0 --- /dev/null +++ b/apps/csharp/texteditor/meson.build @@ -0,0 +1,10 @@ +project( + 'efl-example-texteditor', 'cs', + version : '0.0.1', + meson_version : '>= 0.38.0') + +efl_mono = dependency('efl-mono', version : '>=1.20.99') +efl_mono_libs = efl_mono.get_pkgconfig_variable('mono_libs') + +subdir('src') + diff --git a/apps/csharp/texteditor/src/meson.build b/apps/csharp/texteditor/src/meson.build new file mode 100644 index 0000000..d9ce016 --- /dev/null +++ b/apps/csharp/texteditor/src/meson.build @@ -0,0 +1,12 @@ +src = files([ + 'texteditor_main.cs', +]) + +deps = [efl_mono] + +executable('efl_example_texteditor', src, + dependencies : deps, + cs_args : efl_mono_libs, + install : true +) + diff --git a/apps/csharp/texteditor/src/texteditor_main.cs b/apps/csharp/texteditor/src/texteditor_main.cs new file mode 100644 index 0000000..c70a809 --- /dev/null +++ b/apps/csharp/texteditor/src/texteditor_main.cs @@ -0,0 +1,143 @@ +using System; + +public class TextEditor : IDisposable +{ + private efl.ui.Win win; + private efl.ui.Text editor; + private efl.ui.Button toolbarNew; + + private bool edited = false; + + + private void GUINewClickedCb(object sender, EventArgs ea) + { + editor.SetText(""); + edited = true; + GUIToolbarRefresh(); + } + + private void GUIQuitCb(object sender, EventArgs ea) + { + efl.ui.Config.Exit(); + } + + private void EditorChangedCb(object sender, EventArgs ea) + { + edited = true; + GUIToolbarRefresh(); + } + + private efl.ui.Button GUIToolbarButtonAdd(efl.ui.Box toolbar, string name, string iconName, EventHandler func) + { + efl.ui.Button button = new efl.ui.ButtonConcrete(toolbar); + button.SetText(name); + button.CLICKED += func; + + toolbar.Pack(button); + + efl.ui.Image img = new efl.ui.ImageConcrete(toolbar); + img.SetIcon(iconName); + + efl.ContentConcrete.static_cast(button.Part("elm.swallow.content")).SetContent(img); + + return button; + } + + private void GUIToolbarSetup(efl.ui.Box parent) + { + efl.ui.Box bar = new efl.ui.BoxConcrete(parent); + bar.SetHintWeight(1, 0); + bar.SetDirection(efl.ui.Dir.Horizontal); + parent.Pack(bar); + + toolbarNew = GUIToolbarButtonAdd(bar, "New", "document-new", GUINewClickedCb); + + // spacer box + efl.ui.Box box = new efl.ui.BoxConcrete(parent); + box.SetHintWeight(10, 0); + bar.Pack(box); + + GUIToolbarButtonAdd(bar, "Quit", "application-exit", GUIQuitCb); + + GUIToolbarRefresh(); + } + + private void GUIToolbarRefresh() + { + toolbarNew.SetDisabled(!edited); + } + + public TextEditor() + { + win = new efl.ui.WinConcrete(null, (efl.ui.Win ewin) => { + ewin.SetWinType(efl.ui.win.Type.Basic); + ewin.SetText("Text Editor"); + ewin.SetAutohide(true); + }); + + // when the user clicks "close" on a window there is a request to hide + win.HIDE += GUIQuitCb; + + efl.ui.Box box = new efl.ui.BoxConcrete(win); + eina.Size2D sz; + sz.W = 360; + sz.H = 240; + box.SetHintMin(sz); + + win.SetContent(box); + + GUIToolbarSetup(box); + + editor = new efl.ui.TextConcrete(box); + editor.SetFont("Mono", 14); + editor.SetMultiline(true); + editor.SetEditable(true); + editor.SetScrollable(true); + editor.SetScrollable(true); + editor.CHANGED += EditorChangedCb; + editor.CHANGED_USER += EditorChangedCb; + + box.Pack(editor); + } + + ~TextEditor() + { + Dispose(false); + } + + protected void Dispose(bool disposing) + { + editor.Dispose(); + toolbarNew.Dispose(); + win.Dispose(); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public void Run() + { + // start main loop + efl.ui.Config.Run(); + } +} + +public class Example +{ + public static void Main() + { + efl.All.Init(efl.Components.Ui); + + var textEditor = new TextEditor(); + textEditor.Run(); + + // dispose after quit + textEditor.Dispose(); + + efl.All.Shutdown(); + } +} + --