Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/status bar #197

Closed
wants to merge 12 commits into from
22 changes: 19 additions & 3 deletions StandaloneExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,14 @@ static void Close ()
MessageBox.ErrorQuery (50, 5, "Error", "There is nothing to close", "Ok");
}

static void Help() {
MessageBox.Query(50, 7, "Help", "This is a small help\nBe kind.", "Ok");
}

static void ExitProgram() {
if (Quit ()) Application.Top.Running = false;
}

public static Label ml;
static void Main ()
{
Expand All @@ -185,7 +193,7 @@ static void Main ()
new MenuItem ("_New", "Creates new file", NewFile),
new MenuItem ("_Open", "", null),
new MenuItem ("_Close", "", () => Close ()),
new MenuItem ("_Quit", "", () => { if (Quit ()) top.Running = false; })
new MenuItem ("_Quit", "^X", () => ExitProgram())
}),
new MenuBarItem ("_Edit", new MenuItem [] {
new MenuItem ("_Copy", "", null),
Expand All @@ -194,6 +202,14 @@ static void Main ()
})
});

var statusBar = new StatusBar(new StatusItem[] {
new StatusItem(Key.F1, "~F1~ Help", () => Help()),
new StatusItem(Key.F2, "~F2~ Load", null),
new StatusItem(Key.F3, "~F3~ Save", null),
new StatusItem(Key.ControlX, "~^X~ Quit", () => ExitProgram()),
});


ShowEntries (win);
int count = 0;
ml = new Label (new Rect (3, 17, 47, 1), "Mouse: ");
Expand All @@ -203,8 +219,8 @@ static void Main ()

win.Add (ml);

top.Add (win, menu);
top.Add (menu);
top.Add (win, menu, statusBar);

Application.Run ();
}
}
3 changes: 2 additions & 1 deletion StandaloneExample/StandaloneExample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Terminal.Gui" Version="0.17.0" />
<ProjectReference Include="..\Terminal.Gui\Terminal.Gui.csproj" />
<!-- PackageReference Include="Terminal.Gui" Version="0.17.0" / -->
</ItemGroup>
</Project>
4 changes: 4 additions & 0 deletions Terminal.Gui/Drivers/ConsoleDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ public class ColorScheme {
/// </summary>
public Attribute Normal;
/// <summary>
/// The default color for text, when the view is disabled.
/// </summary>
public Attribute Disabled;
/// <summary>
/// The color for text when the view has the focus.
/// </summary>
public Attribute Focus;
Expand Down
5 changes: 3 additions & 2 deletions Terminal.Gui/Drivers/CursesDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,9 @@ public override void Init (Action terminalResized)
Colors.Menu.Focus = Curses.A_BOLD | MakeColor (Curses.COLOR_WHITE, Curses.COLOR_BLACK);
Colors.Menu.HotNormal = Curses.A_BOLD | MakeColor (Curses.COLOR_YELLOW, Curses.COLOR_CYAN);
Colors.Menu.Normal = Curses.A_BOLD | MakeColor (Curses.COLOR_WHITE, Curses.COLOR_CYAN);

Colors.Dialog.Normal = MakeColor (Curses.COLOR_BLACK, Curses.COLOR_WHITE);
Colors.Menu.Disabled = MakeColor(Curses.COLOR_WHITE, Curses.COLOR_CYAN);

Colors.Dialog.Normal = MakeColor (Curses.COLOR_BLACK, Curses.COLOR_WHITE);
Colors.Dialog.Focus = MakeColor (Curses.COLOR_BLACK, Curses.COLOR_CYAN);
Colors.Dialog.HotNormal = MakeColor (Curses.COLOR_BLUE, Curses.COLOR_WHITE);
Colors.Dialog.HotFocus = MakeColor (Curses.COLOR_BLUE, Curses.COLOR_CYAN);
Expand Down
1 change: 1 addition & 0 deletions Terminal.Gui/Drivers/NetDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ public override void Init (Action terminalResized)
Colors.Menu.Focus = MakeColor (ConsoleColor.White, ConsoleColor.Black);
Colors.Menu.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Cyan);
Colors.Menu.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Cyan);
Colors.Menu.Disabled = MakeColor(ConsoleColor.DarkGray, ConsoleColor.Cyan);

Colors.Dialog.Normal = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
Colors.Dialog.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Cyan);
Expand Down
1 change: 1 addition & 0 deletions Terminal.Gui/Drivers/WindowsDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,7 @@ public override void Init (Action terminalResized)
Colors.Menu.Focus = MakeColor (ConsoleColor.White, ConsoleColor.Black);
Colors.Menu.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Cyan);
Colors.Menu.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Cyan);
Colors.Menu.Disabled = MakeColor(ConsoleColor.DarkGray, ConsoleColor.Cyan);

Colors.Dialog.Normal = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
Colors.Dialog.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Cyan);
Expand Down
121 changes: 82 additions & 39 deletions Terminal.Gui/Views/Menu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ public class MenuItem {
/// <param name="title">Title for the menu item.</param>
/// <param name="help">Help text to display.</param>
/// <param name="action">Action to invoke when the menu item is activated.</param>
public MenuItem (ustring title, string help, Action action)
/// <param name="canExecute">Function to determine if the action can currently be executred.</param>
public MenuItem (ustring title, string help, Action action, Func<bool> canExecute=null)
{
Title = title ?? "";
Help = help ?? "";
Action = action;
CanExecute = canExecute;
bool nextIsHot = false;
foreach (var x in Title) {
if (x == '_')
Expand Down Expand Up @@ -76,6 +78,13 @@ public MenuItem (ustring title, string help, Action action)
/// </summary>
/// <value>Method to invoke.</value>
public Action Action { get; set; }

/// <summary>
/// Gets or sets the action to be invoked if the menu can be triggered
/// </summary>
/// <value>Function to determine if action is ready to be executed.</value>
public Func<bool> CanExecute { get; set; }

internal int Width => Title.Length + Help.Length + 1 + 2;
}

Expand Down Expand Up @@ -126,19 +135,24 @@ static Rect MakeFrame (int x, int y, MenuItem [] items)
{
int maxW = 0;

foreach (var item in items) {
foreach (var item in items)
{
if (item == null) continue;
var l = item.Width;
maxW = Math.Max (l, maxW);
}
return new Rect (x, y, maxW + 2, items.Length + 2);
}

void CalculateCurrentItem(MenuItem [] items)
{
current = -1;
for (int i = 0; i < items.Length; i++) {
if (items [i] != null) {
current = i;
break;
return;
}
}
return new Rect (x, y, maxW + 2, items.Length + 2);
}

public Menu (MenuBar host, int x, int y, MenuBarItem barItems) : base (MakeFrame (x, y, barItems.Children))
Expand All @@ -147,6 +161,17 @@ public Menu (MenuBar host, int x, int y, MenuBarItem barItems) : base (MakeFrame
this.host = host;
ColorScheme = Colors.Menu;
CanFocus = true;
CalculateCurrentItem(barItems.Children);
}

internal Attribute DetermineColorSchemeFor(MenuItem item, int index)
{
if (item!=null)
{
if (index==current) return ColorScheme.Focus;
if (item.CanExecute!=null && !item.CanExecute()) return ColorScheme.Disabled;
}
return ColorScheme.Normal;
}

public override void Redraw (Rect region)
Expand All @@ -156,19 +181,31 @@ public override void Redraw (Rect region)

for (int i = 0; i < barItems.Children.Length; i++){
var item = barItems.Children [i];
Move (1, i+1);
Driver.SetAttribute (item == null ? Colors.Base.Focus : i == current ? ColorScheme.Focus : ColorScheme.Normal);
Driver.SetAttribute(item == null ? ColorScheme.Normal : i == current ? ColorScheme.Focus : ColorScheme.Normal);
if (item == null) {
Move(0, i + 1);
Driver.AddRune(Driver.LeftTee);
} else {
Move(1, i+1);
}

for (int p = 0; p < Frame.Width-2; p++)
if (item == null)
Driver.AddRune (Driver.HLine);
else
Driver.AddRune (' ');

if (item == null)
continue;

Move (2, i + 1);
DrawHotString (item.Title,
if (item == null) {
Move(region.Right-1, i + 1);
Driver.AddRune(Driver.RightTee);
continue;
}

Move (2, i + 1);
if (item.CanExecute != null && !item.CanExecute())
DrawHotString (item.Title, ColorScheme.Disabled, ColorScheme.Disabled);
else
DrawHotString (item.Title,
i == current? ColorScheme.HotFocus : ColorScheme.HotNormal,
i == current ? ColorScheme.Focus : ColorScheme.Normal);

Expand Down Expand Up @@ -197,23 +234,30 @@ void Run (Action action)

public override bool ProcessKey (KeyEvent kb)
{
bool disabled;
switch (kb.Key) {
case Key.CursorUp:
if (current == -1)
break;
do {
disabled = false;
current--;
if (current < 0)
current = barItems.Children.Length - 1;
} while (barItems.Children [current] == null)
var item = barItems.Children[current];
if (item!=null && item.CanExecute != null && !item.CanExecute()) disabled = true;
} while (barItems.Children [current] == null || disabled);
SetNeedsDisplay ();
break;
case Key.CursorDown:
do {
disabled = false;
current++;
if (current == barItems.Children.Length)
current = 0;
} while (barItems.Children [current] == null)
var item = barItems.Children[current];
if (item !=null && item.CanExecute != null && !item.CanExecute()) disabled = true;
} while (barItems.Children [current] == null || disabled);
SetNeedsDisplay ();
break;
case Key.CursorLeft:
Expand Down Expand Up @@ -315,7 +359,7 @@ public override void Redraw (Rect region)
var menu = Menus [i];
Move (pos, 0);
Attribute hotColor, normalColor;
if (i == selected){
if (i == selected) {
hotColor = i == selected ? ColorScheme.HotFocus : ColorScheme.HotNormal;
normalColor = i == selected ? ColorScheme.Focus : ColorScheme.Normal;
} else {
Expand Down Expand Up @@ -421,38 +465,37 @@ internal void NextMenu ()
OpenMenu (selected);
}

internal bool FindAndOpenMenuByHotkey(KeyEvent kb)
{
int pos = 0;
var c = ((uint)kb.Key & (uint)Key.CharMask);
for (int i = 0; i < Menus.Length; i++)
{
// TODO: this code is duplicated, hotkey should be part of the MenuBarItem
var mi = Menus[i];
int p = mi.Title.IndexOf('_');
if (p != -1 && p + 1 < mi.Title.Length) {
if (mi.Title[p + 1] == c) {
OpenMenu(i);
return true;
}
}
}
return false;
}
public override bool ProcessHotKey (KeyEvent kb)
internal bool FindAndOpenMenuByHotkey(KeyEvent kb)
{
int pos = 0;
var c = ((uint)kb.Key & (uint)Key.CharMask);
for (int i = 0; i < Menus.Length; i++)
{
// TODO: this code is duplicated, hotkey should be part of the MenuBarItem
var mi = Menus[i];
int p = mi.Title.IndexOf('_');
if (p != -1 && p + 1 < mi.Title.Length) {
if (mi.Title[p + 1] == c) {
OpenMenu(i);
return true;
}
}
}
return false;
}

public override bool ProcessHotKey (KeyEvent kb)
{
if (kb.Key == Key.F9) {
StartMenu ();
return true;
}

if (kb.IsAlt)
{
if (FindAndOpenMenuByHotkey(kb)) return true;
}
var kc = kb.KeyValue;
if (kb.IsAlt) {
if (FindAndOpenMenuByHotkey(kb)) return true;
}

var kc = kb.KeyValue;
return base.ProcessHotKey (kb);
}

Expand Down
Loading