mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2026-01-01 16:59:35 +01:00
Merge branch 'master' into progress_invoke_fix
This commit is contained in:
@@ -190,7 +190,7 @@ static class Demo {
|
|||||||
new DateField (3, 22, DateTime.Now),
|
new DateField (3, 22, DateTime.Now),
|
||||||
new DateField (23, 22, DateTime.Now, true),
|
new DateField (23, 22, DateTime.Now, true),
|
||||||
progress,
|
progress,
|
||||||
new Label (3, 24, "Press F9 (on Unix, ESC+9 is an alias) to activate the menubar"),
|
new Label (3, 24, "Press F9 (on Unix, ESC+9 is an alias) or Ctrl+T to activate the menubar"),
|
||||||
menuKeysStyle,
|
menuKeysStyle,
|
||||||
menuAutoMouseNav
|
menuAutoMouseNav
|
||||||
|
|
||||||
@@ -636,10 +636,23 @@ static class Demo {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
win.KeyPress += Win_KeyPress;
|
||||||
|
|
||||||
|
|
||||||
top.Add (win);
|
top.Add (win);
|
||||||
//top.Add (menu);
|
//top.Add (menu);
|
||||||
top.Add (menu, statusBar);
|
top.Add (menu, statusBar);
|
||||||
Application.Run ();
|
Application.Run ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void Win_KeyPress (object sender, View.KeyEventEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.KeyEvent.Key == Key.ControlT) {
|
||||||
|
if (menu.IsMenuOpen)
|
||||||
|
menu.CloseMenu ();
|
||||||
|
else
|
||||||
|
menu.OpenMenu ();
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1087,6 +1087,11 @@ namespace Terminal.Gui {
|
|||||||
/// The <see cref="KeyEvent"/> for the event.
|
/// The <see cref="KeyEvent"/> for the event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public KeyEvent KeyEvent { get; set; }
|
public KeyEvent KeyEvent { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the current Key event has already been processed and the driver should stop notifying any other event subscriber.
|
||||||
|
/// Its important to set this value to true specially when updating any View's layout from inside the subscriber method.
|
||||||
|
/// </summary>
|
||||||
|
public bool Handled { get; set; } = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1097,7 +1102,11 @@ namespace Terminal.Gui {
|
|||||||
/// <inheritdoc cref="ProcessKey"/>
|
/// <inheritdoc cref="ProcessKey"/>
|
||||||
public override bool ProcessKey (KeyEvent keyEvent)
|
public override bool ProcessKey (KeyEvent keyEvent)
|
||||||
{
|
{
|
||||||
KeyPress?.Invoke (this, new KeyEventEventArgs(keyEvent));
|
|
||||||
|
KeyEventEventArgs args = new KeyEventEventArgs (keyEvent);
|
||||||
|
KeyPress?.Invoke (this, args);
|
||||||
|
if (args.Handled)
|
||||||
|
return true;
|
||||||
if (Focused?.ProcessKey (keyEvent) == true)
|
if (Focused?.ProcessKey (keyEvent) == true)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -1107,7 +1116,10 @@ namespace Terminal.Gui {
|
|||||||
/// <inheritdoc cref="ProcessHotKey"/>
|
/// <inheritdoc cref="ProcessHotKey"/>
|
||||||
public override bool ProcessHotKey (KeyEvent keyEvent)
|
public override bool ProcessHotKey (KeyEvent keyEvent)
|
||||||
{
|
{
|
||||||
KeyPress?.Invoke (this, new KeyEventEventArgs (keyEvent));
|
KeyEventEventArgs args = new KeyEventEventArgs (keyEvent);
|
||||||
|
KeyPress?.Invoke (this, args);
|
||||||
|
if (args.Handled)
|
||||||
|
return true;
|
||||||
if (subviews == null || subviews.Count == 0)
|
if (subviews == null || subviews.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
foreach (var view in subviews)
|
foreach (var view in subviews)
|
||||||
@@ -1119,7 +1131,10 @@ namespace Terminal.Gui {
|
|||||||
/// <inheritdoc cref="ProcessColdKey"/>
|
/// <inheritdoc cref="ProcessColdKey"/>
|
||||||
public override bool ProcessColdKey (KeyEvent keyEvent)
|
public override bool ProcessColdKey (KeyEvent keyEvent)
|
||||||
{
|
{
|
||||||
KeyPress?.Invoke (this, new KeyEventEventArgs(keyEvent));
|
KeyEventEventArgs args = new KeyEventEventArgs (keyEvent);
|
||||||
|
KeyPress?.Invoke (this, args);
|
||||||
|
if (args.Handled)
|
||||||
|
return true;
|
||||||
if (subviews == null || subviews.Count == 0)
|
if (subviews == null || subviews.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
foreach (var view in subviews)
|
foreach (var view in subviews)
|
||||||
@@ -1136,7 +1151,10 @@ namespace Terminal.Gui {
|
|||||||
/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
|
/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
|
||||||
public override bool OnKeyDown (KeyEvent keyEvent)
|
public override bool OnKeyDown (KeyEvent keyEvent)
|
||||||
{
|
{
|
||||||
KeyDown?.Invoke (this, new KeyEventEventArgs (keyEvent));
|
KeyEventEventArgs args = new KeyEventEventArgs (keyEvent);
|
||||||
|
KeyDown?.Invoke (this, args);
|
||||||
|
if (args.Handled)
|
||||||
|
return true;
|
||||||
if (subviews == null || subviews.Count == 0)
|
if (subviews == null || subviews.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
foreach (var view in subviews)
|
foreach (var view in subviews)
|
||||||
@@ -1154,7 +1172,10 @@ namespace Terminal.Gui {
|
|||||||
/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
|
/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
|
||||||
public override bool OnKeyUp (KeyEvent keyEvent)
|
public override bool OnKeyUp (KeyEvent keyEvent)
|
||||||
{
|
{
|
||||||
KeyUp?.Invoke (this, new KeyEventEventArgs (keyEvent));
|
KeyEventEventArgs args = new KeyEventEventArgs (keyEvent);
|
||||||
|
KeyUp?.Invoke (this, args);
|
||||||
|
if (args.Handled)
|
||||||
|
return true;
|
||||||
if (subviews == null || subviews.Count == 0)
|
if (subviews == null || subviews.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
foreach (var view in subviews)
|
foreach (var view in subviews)
|
||||||
|
|||||||
@@ -784,7 +784,7 @@ namespace Terminal.Gui {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Closes the current Menu programatically, if open.
|
/// Closes the current Menu programatically, if open.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void CloseMenu()
|
public void CloseMenu ()
|
||||||
{
|
{
|
||||||
CloseMenu (false, false);
|
CloseMenu (false, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,280 +0,0 @@
|
|||||||
using NStack;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using Terminal.Gui;
|
|
||||||
|
|
||||||
namespace UICatalog {
|
|
||||||
/// <summary>
|
|
||||||
/// Main program for the Terminal.gui UI Catalog app. This app provides a chooser that allows
|
|
||||||
/// for a calalog of UI demos, examples, and tests.
|
|
||||||
/// </summary>
|
|
||||||
internal class Program {
|
|
||||||
private static Toplevel _top;
|
|
||||||
private static MenuBar _menu;
|
|
||||||
private static int _nameColumnWidth;
|
|
||||||
private static Window _leftPane;
|
|
||||||
private static List<string> _categories;
|
|
||||||
private static ListView _categoryListView;
|
|
||||||
private static Window _rightPane;
|
|
||||||
private static List<Type> _scenarios;
|
|
||||||
private static ListView _scenarioListView;
|
|
||||||
private static StatusBar _statusBar;
|
|
||||||
|
|
||||||
private static Scenario _selectedScenario = null;
|
|
||||||
|
|
||||||
static void Main (string [] args)
|
|
||||||
{
|
|
||||||
if (Debugger.IsAttached)
|
|
||||||
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
|
|
||||||
|
|
||||||
_scenarios = Scenario.GetDerivedClassesCollection ().OrderBy (t => Scenario.ScenarioMetadata.GetName (t)).ToList();
|
|
||||||
|
|
||||||
if (args.Length > 0) {
|
|
||||||
var item = _scenarios.FindIndex (t => Scenario.ScenarioMetadata.GetName (t).Equals (args [0], StringComparison.OrdinalIgnoreCase));
|
|
||||||
_selectedScenario = (Scenario)Activator.CreateInstance (_scenarios [item]);
|
|
||||||
_selectedScenario.Init (Application.Top);
|
|
||||||
_selectedScenario.Setup ();
|
|
||||||
_selectedScenario.Run ();
|
|
||||||
_selectedScenario = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Scenario scenario = GetScenarioToRun ();
|
|
||||||
while (scenario != null) {
|
|
||||||
scenario.Init (Application.Top);
|
|
||||||
scenario.Setup ();
|
|
||||||
scenario.Run ();
|
|
||||||
scenario = GetScenarioToRun ();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create all controls. This gets called once and the controls remain with their state between Sceanrio runs.
|
|
||||||
/// </summary>
|
|
||||||
private static void Setup ()
|
|
||||||
{
|
|
||||||
_menu = new MenuBar (new MenuBarItem [] {
|
|
||||||
new MenuBarItem ("_File", new MenuItem [] {
|
|
||||||
new MenuItem ("_Quit", "", () => Application.RequestStop() )
|
|
||||||
}),
|
|
||||||
new MenuBarItem ("_About...", "About this app", () => MessageBox.Query (0, 10, "About UI Catalog", "UI Catalog is a comprehensive sample library for Terminal.Gui", "Ok")),
|
|
||||||
});
|
|
||||||
|
|
||||||
_leftPane = new Window ("Categories") {
|
|
||||||
X = 0,
|
|
||||||
Y = 1, // for menu
|
|
||||||
Width = 25,
|
|
||||||
Height = Dim.Fill (),
|
|
||||||
CanFocus = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
_categories = Scenario.GetAllCategories ().OrderBy(c => c).ToList();
|
|
||||||
_categoryListView = new ListView (_categories) {
|
|
||||||
X = 1,
|
|
||||||
Y = 0,
|
|
||||||
Width = Dim.Fill (0),
|
|
||||||
Height = Dim.Fill (2),
|
|
||||||
AllowsMarking = false,
|
|
||||||
CanFocus = true,
|
|
||||||
};
|
|
||||||
_categoryListView.OpenSelectedItem += (o, a) => {
|
|
||||||
_top.SetFocus (_rightPane);
|
|
||||||
};
|
|
||||||
_categoryListView.SelectedChanged += CategoryListView_SelectedChanged;
|
|
||||||
_leftPane.Add (_categoryListView);
|
|
||||||
|
|
||||||
_rightPane = new Window ("Scenarios") {
|
|
||||||
X = 25,
|
|
||||||
Y = 1, // for menu
|
|
||||||
Width = Dim.Fill (),
|
|
||||||
Height = Dim.Fill (),
|
|
||||||
CanFocus = false,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
_nameColumnWidth = Scenario.ScenarioMetadata.GetName (_scenarios.OrderByDescending (t => Scenario.ScenarioMetadata.GetName (t).Length).FirstOrDefault ()).Length;
|
|
||||||
|
|
||||||
_scenarioListView = new ListView () {
|
|
||||||
X = 0,
|
|
||||||
Y = 0,
|
|
||||||
Width = Dim.Fill (0),
|
|
||||||
Height = Dim.Fill (0),
|
|
||||||
AllowsMarking = false,
|
|
||||||
CanFocus = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
//_scenarioListView.OnKeyPress += (KeyEvent ke) => {
|
|
||||||
// if (_top.MostFocused == _scenarioListView && ke.Key == Key.Enter) {
|
|
||||||
// _scenarioListView_OpenSelectedItem (null, null);
|
|
||||||
// }
|
|
||||||
//};
|
|
||||||
|
|
||||||
_scenarioListView.OpenSelectedItem += _scenarioListView_OpenSelectedItem;
|
|
||||||
_rightPane.Add (_scenarioListView);
|
|
||||||
|
|
||||||
_categoryListView.SelectedItem = 0;
|
|
||||||
_categoryListView.OnSelectedChanged ();
|
|
||||||
|
|
||||||
_statusBar = new StatusBar (new StatusItem [] {
|
|
||||||
//new StatusItem(Key.F1, "~F1~ Help", () => Help()),
|
|
||||||
new StatusItem(Key.ControlQ, "~CTRL-Q~ Quit", () => {
|
|
||||||
if (_selectedScenario is null){
|
|
||||||
// This causes GetScenarioToRun to return null
|
|
||||||
_selectedScenario = null;
|
|
||||||
Application.RequestStop();
|
|
||||||
} else {
|
|
||||||
_selectedScenario.RequestStop();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This shows the selection UI. Each time it is run, it calls Application.Init to reset everything.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private static Scenario GetScenarioToRun ()
|
|
||||||
{
|
|
||||||
Application.Init ();
|
|
||||||
|
|
||||||
if (_menu == null) {
|
|
||||||
Setup ();
|
|
||||||
}
|
|
||||||
|
|
||||||
_top = Application.Top;
|
|
||||||
|
|
||||||
_top.KeyUp += KeyUpHandler;
|
|
||||||
|
|
||||||
_top.Add (_menu);
|
|
||||||
_top.Add (_leftPane);
|
|
||||||
_top.Add (_rightPane);
|
|
||||||
_top.Add (_statusBar);
|
|
||||||
|
|
||||||
// HACK: There is no other way to SetFocus before Application.Run. See Issue #445
|
|
||||||
#if false
|
|
||||||
if (_runningScenario != null)
|
|
||||||
Application.Iteration += Application_Iteration;
|
|
||||||
#else
|
|
||||||
_top.Ready += (o, a) => {
|
|
||||||
if (_selectedScenario != null) {
|
|
||||||
_top.SetFocus (_rightPane);
|
|
||||||
_selectedScenario = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Application.Run (_top);
|
|
||||||
Application.Shutdown ();
|
|
||||||
return _selectedScenario;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if false
|
|
||||||
private static void Application_Iteration (object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Application.Iteration -= Application_Iteration;
|
|
||||||
_top.SetFocus (_rightPane);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
private static void _scenarioListView_OpenSelectedItem (object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (_selectedScenario is null) {
|
|
||||||
var source = _scenarioListView.Source as ScenarioListDataSource;
|
|
||||||
_selectedScenario = (Scenario)Activator.CreateInstance (source.Scenarios [_scenarioListView.SelectedItem]);
|
|
||||||
Application.RequestStop ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class ScenarioListDataSource : IListDataSource {
|
|
||||||
public List<Type> Scenarios { get; set; }
|
|
||||||
|
|
||||||
public bool IsMarked (int item) => false;// Scenarios [item].IsMarked;
|
|
||||||
|
|
||||||
public int Count => Scenarios.Count;
|
|
||||||
|
|
||||||
public ScenarioListDataSource (List<Type> itemList) => Scenarios = itemList;
|
|
||||||
|
|
||||||
public void Render (ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width)
|
|
||||||
{
|
|
||||||
container.Move (col, line);
|
|
||||||
// Equivalent to an interpolated string like $"{Scenarios[item].Name, -widtestname}"; if such a thing were possible
|
|
||||||
var s = String.Format (String.Format ("{{0,{0}}}", -_nameColumnWidth), Scenario.ScenarioMetadata.GetName (Scenarios [item]));
|
|
||||||
RenderUstr (driver, $"{s} {Scenario.ScenarioMetadata.GetDescription (Scenarios [item])}", col, line, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetMark (int item, bool value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// A slightly adapted method from: https://github.com/migueldeicaza/gui.cs/blob/fc1faba7452ccbdf49028ac49f0c9f0f42bbae91/Terminal.Gui/Views/ListView.cs#L433-L461
|
|
||||||
private void RenderUstr (ConsoleDriver driver, ustring ustr, int col, int line, int width)
|
|
||||||
{
|
|
||||||
int used = 0;
|
|
||||||
int index = 0;
|
|
||||||
while (index < ustr.Length) {
|
|
||||||
(var rune, var size) = Utf8.DecodeRune (ustr, index, index - ustr.Length);
|
|
||||||
var count = Rune.ColumnWidth (rune);
|
|
||||||
if (used + count >= width) break;
|
|
||||||
driver.AddRune (rune);
|
|
||||||
used += count;
|
|
||||||
index += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (used < width) {
|
|
||||||
driver.AddRune (' ');
|
|
||||||
used++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IList ToList ()
|
|
||||||
{
|
|
||||||
return Scenarios;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// When Scenarios are running we need to override the behavior of the Menu
|
|
||||||
/// and Statusbar to enable Scenarios that use those (or related key input)
|
|
||||||
/// to not be impacted. Same as for tabs.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ke"></param>
|
|
||||||
private static void KeyUpHandler (object sender, View.KeyEventEventArgs a)
|
|
||||||
{
|
|
||||||
if (_selectedScenario != null) {
|
|
||||||
//switch (ke.Key) {
|
|
||||||
//case Key.Esc:
|
|
||||||
// //_runningScenario.RequestStop ();
|
|
||||||
// break;
|
|
||||||
//case Key.Enter:
|
|
||||||
// break;
|
|
||||||
//}<
|
|
||||||
} else if (a.KeyEvent.Key == Key.Tab || a.KeyEvent.Key == Key.BackTab) {
|
|
||||||
// BUGBUG: Work around Issue #434 by implementing our own TAB navigation
|
|
||||||
if (_top.MostFocused == _categoryListView)
|
|
||||||
_top.SetFocus (_rightPane);
|
|
||||||
else
|
|
||||||
_top.SetFocus (_leftPane);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CategoryListView_SelectedChanged (object sender, ListViewItemEventArgs e)
|
|
||||||
{
|
|
||||||
var item = _categories [_categoryListView.SelectedItem];
|
|
||||||
List<Type> newlist;
|
|
||||||
if (item.Equals ("All")) {
|
|
||||||
newlist = _scenarios;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
newlist = _scenarios.Where (t => Scenario.ScenarioCategory.GetCategories (t).Contains (item)).ToList ();
|
|
||||||
}
|
|
||||||
_scenarioListView.Source = new ScenarioListDataSource (newlist);
|
|
||||||
_scenarioListView.SelectedItem = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
162
UICatalog/Scenarios/Threading.cs
Normal file
162
UICatalog/Scenarios/Threading.cs
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "Threading", Description: "Demonstration of how to use threading in different ways")]
|
||||||
|
[ScenarioCategory ("Threading")]
|
||||||
|
class Threading : Scenario {
|
||||||
|
private Action _action;
|
||||||
|
private Action _lambda;
|
||||||
|
private EventHandler _handler;
|
||||||
|
private Action _sync;
|
||||||
|
|
||||||
|
private ListView _itemsList;
|
||||||
|
private Button _btnActionCancel;
|
||||||
|
List<string> log = new List<string> ();
|
||||||
|
private ListView _logJob;
|
||||||
|
|
||||||
|
public override void Setup ()
|
||||||
|
{
|
||||||
|
_action = LoadData;
|
||||||
|
_lambda = async () => {
|
||||||
|
_itemsList.Source = null;
|
||||||
|
LogJob ("Loading task lambda");
|
||||||
|
var items = await LoadDataAsync ();
|
||||||
|
LogJob ("Returning from task lambda");
|
||||||
|
_itemsList.SetSource (items);
|
||||||
|
};
|
||||||
|
_handler = async (s, e) => {
|
||||||
|
_itemsList.Source = null;
|
||||||
|
LogJob ("Loading task handler");
|
||||||
|
var items = await LoadDataAsync ();
|
||||||
|
LogJob ("Returning from task handler");
|
||||||
|
_itemsList.SetSource (items);
|
||||||
|
|
||||||
|
};
|
||||||
|
_sync = () => {
|
||||||
|
_itemsList.Source = null;
|
||||||
|
LogJob ("Loading task synchronous");
|
||||||
|
List<string> items = new List<string> () { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten" };
|
||||||
|
LogJob ("Returning from task synchronous");
|
||||||
|
_itemsList.SetSource (items);
|
||||||
|
};
|
||||||
|
|
||||||
|
Application.Init ();
|
||||||
|
|
||||||
|
_btnActionCancel = new Button (1, 1, "Cancelable Load Items");
|
||||||
|
_btnActionCancel.Clicked += () => Application.MainLoop.Invoke (CallLoadItemsAsync);
|
||||||
|
|
||||||
|
_itemsList = new ListView {
|
||||||
|
X = Pos.X (_btnActionCancel),
|
||||||
|
Y = Pos.Y (_btnActionCancel) + 4,
|
||||||
|
Width = 10,
|
||||||
|
Height = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
_logJob = new ListView (log) {
|
||||||
|
X = Pos.Right (_itemsList) + 10,
|
||||||
|
Y = Pos.Y (_itemsList),
|
||||||
|
Width = 50,
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
|
||||||
|
var text = new TextField (1, 3, 100, "Type anything after press the button");
|
||||||
|
|
||||||
|
var _btnAction = new Button (80, 10, "Load Data Action");
|
||||||
|
_btnAction.Clicked += () => _action.Invoke ();
|
||||||
|
var _btnLambda = new Button (80, 12, "Load Data Lambda");
|
||||||
|
_btnLambda.Clicked += () => _lambda.Invoke ();
|
||||||
|
var _btnHandler = new Button (80, 14, "Load Data Handler");
|
||||||
|
_btnHandler.Clicked += () => _handler.Invoke (null, new EventArgs ());
|
||||||
|
var _btnSync = new Button (80, 16, "Load Data Synchronous");
|
||||||
|
_btnSync.Clicked += () => _sync.Invoke ();
|
||||||
|
var _btnMethod = new Button (80, 18, "Load Data Method");
|
||||||
|
_btnMethod.Clicked += async () => await MethodAsync ();
|
||||||
|
var _btnClearData = new Button (80, 20, "Clear Data");
|
||||||
|
_btnClearData.Clicked += () => { _itemsList.Source = null; LogJob ("Cleaning Data"); };
|
||||||
|
var _btnQuit = new Button (80, 22, "Quit");
|
||||||
|
_btnQuit.Clicked += Application.RequestStop;
|
||||||
|
|
||||||
|
Win.Add (_itemsList, _btnActionCancel, _logJob, text, _btnAction, _btnLambda, _btnHandler, _btnSync, _btnMethod, _btnClearData, _btnQuit);
|
||||||
|
Application.Top.Add (Win);
|
||||||
|
Application.Run ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void LoadData ()
|
||||||
|
{
|
||||||
|
_itemsList.Source = null;
|
||||||
|
LogJob ("Loading task");
|
||||||
|
var items = await LoadDataAsync ();
|
||||||
|
LogJob ("Returning from task");
|
||||||
|
_itemsList.SetSource (items);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LogJob (string job)
|
||||||
|
{
|
||||||
|
log.Add (job);
|
||||||
|
_logJob.MoveDown ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<string>> LoadDataAsync ()
|
||||||
|
{
|
||||||
|
_itemsList.Source = null;
|
||||||
|
LogJob ("Starting delay");
|
||||||
|
await Task.Delay (3000);
|
||||||
|
LogJob ("Finished delay");
|
||||||
|
return new List<string> () { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten" };
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task MethodAsync ()
|
||||||
|
{
|
||||||
|
_itemsList.Source = null;
|
||||||
|
LogJob ("Loading task method");
|
||||||
|
List<string> items = new List<string> () { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten" };
|
||||||
|
await Task.Delay (3000);
|
||||||
|
LogJob ("Returning from task method");
|
||||||
|
await _itemsList.SetSourceAsync (items);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CancellationTokenSource cancellationTokenSource;
|
||||||
|
|
||||||
|
private async void CallLoadItemsAsync ()
|
||||||
|
{
|
||||||
|
cancellationTokenSource = new CancellationTokenSource ();
|
||||||
|
_itemsList.Source = null;
|
||||||
|
LogJob ($"Clicked the button");
|
||||||
|
if (_btnActionCancel.Text == "Cancel") {
|
||||||
|
_btnActionCancel.Text = "Cancelable Load Items";
|
||||||
|
cancellationTokenSource.Cancel ();
|
||||||
|
} else
|
||||||
|
_btnActionCancel.Text = "Cancel";
|
||||||
|
try {
|
||||||
|
if (cancellationTokenSource.Token.IsCancellationRequested)
|
||||||
|
cancellationTokenSource.Token.ThrowIfCancellationRequested ();
|
||||||
|
LogJob ($"Calling task Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
|
||||||
|
var items = await Task.Run (LoadItemsAsync, cancellationTokenSource.Token);
|
||||||
|
if (!cancellationTokenSource.IsCancellationRequested) {
|
||||||
|
LogJob ($"Returned from task Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
|
||||||
|
_itemsList.SetSource (items);
|
||||||
|
LogJob ($"Finished populate list view Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
|
||||||
|
_btnActionCancel.Text = "Load Items";
|
||||||
|
} else {
|
||||||
|
LogJob ("Task was canceled!");
|
||||||
|
}
|
||||||
|
} catch (OperationCanceledException ex) {
|
||||||
|
LogJob (ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<string>> LoadItemsAsync ()
|
||||||
|
{
|
||||||
|
// Do something that takes lot of times.
|
||||||
|
LogJob ($"Starting delay Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
|
||||||
|
await Task.Delay (5000);
|
||||||
|
LogJob ($"Finished delay Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
|
||||||
|
return new List<string> () { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user