From fc9a6d5746459e23ef2deaaab7d334e64f021b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Sun, 2 Feb 2020 23:39:45 +0000 Subject: [PATCH 01/10] Updated obsolete API usages. --- src/Avalonia.Controls.DataGrid/DataGrid.cs | 32 +++++++++---------- .../DataGridColumnHeader.cs | 16 +++++----- .../Utils/KeyboardHelper.cs | 15 +++++---- src/Avalonia.Controls/Calendar/Calendar.cs | 4 +-- .../Calendar/CalendarExtensions.cs | 6 ++-- .../Calendar/CalendarItem.cs | 2 +- src/Avalonia.Controls/Calendar/DatePicker.cs | 2 +- src/Avalonia.Controls/ComboBox.cs | 2 +- .../SelectingItemsControlSelectionAdapter.cs | 2 +- .../KeyboardNavigationHandler.cs | 2 +- 10 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs index 86133d5fdb..e16e11cdd6 100644 --- a/src/Avalonia.Controls.DataGrid/DataGrid.cs +++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs @@ -2472,25 +2472,25 @@ namespace Avalonia.Controls internal bool ProcessDownKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); return ProcessDownKeyInternal(shift, ctrl); } internal bool ProcessEndKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); return ProcessEndKey(shift, ctrl); } internal bool ProcessEnterKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); return ProcessEnterKey(shift, ctrl); } internal bool ProcessHomeKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); return ProcessHomeKey(shift, ctrl); } @@ -2530,25 +2530,25 @@ namespace Avalonia.Controls internal bool ProcessLeftKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); return ProcessLeftKey(shift, ctrl); } internal bool ProcessNextKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); return ProcessNextKey(shift, ctrl); } internal bool ProcessPriorKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); return ProcessPriorKey(shift, ctrl); } internal bool ProcessRightKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); return ProcessRightKey(shift, ctrl); } @@ -2666,7 +2666,7 @@ namespace Avalonia.Controls internal bool ProcessUpKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); return ProcessUpKey(shift, ctrl); } @@ -2934,7 +2934,7 @@ namespace Avalonia.Controls //TODO: Ensure left button is checked for internal bool UpdateStateOnMouseLeftButtonDown(PointerPressedEventArgs pointerPressedEventArgs, int columnIndex, int slot, bool allowEdit) { - KeyboardHelper.GetMetaKeyState(pointerPressedEventArgs.InputModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(pointerPressedEventArgs.KeyModifiers, out bool ctrl, out bool shift); return UpdateStateOnMouseLeftButtonDown(pointerPressedEventArgs, columnIndex, slot, allowEdit, shift, ctrl); } @@ -4376,7 +4376,7 @@ namespace Avalonia.Controls private bool ProcessAKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift, out bool alt); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift, out bool alt); if (ctrl && !shift && !alt && SelectionMode == DataGridSelectionMode.Extended) { @@ -4442,10 +4442,10 @@ namespace Avalonia.Controls return ProcessAKey(e); case Key.C: - return ProcessCopyKey(e.Modifiers); + return ProcessCopyKey(e.KeyModifiers); case Key.Insert: - return ProcessCopyKey(e.Modifiers); + return ProcessCopyKey(e.KeyModifiers); } if (focusDataGrid) { @@ -4644,7 +4644,7 @@ namespace Avalonia.Controls private bool ProcessF2Key(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); if (!shift && !ctrl && _editingColumnIndex == -1 && CurrentColumnIndex != -1 && GetRowSelection(CurrentSlot) && @@ -5001,7 +5001,7 @@ namespace Avalonia.Controls private bool ProcessTabKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); return ProcessTabKey(e, shift, ctrl); } @@ -5787,7 +5787,7 @@ namespace Avalonia.Controls /// to the Clipboard as text. /// /// Whether or not the DataGrid handled the key press. - private bool ProcessCopyKey(InputModifiers modifiers) + private bool ProcessCopyKey(KeyModifiers modifiers) { KeyboardHelper.GetMetaKeyState(modifiers, out bool ctrl, out bool shift, out bool alt); diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs index d1651b2d09..062fdeb4d3 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs @@ -190,28 +190,28 @@ namespace Avalonia.Controls } } - internal void OnMouseLeftButtonUp_Click(InputModifiers inputModifiers, ref bool handled) + internal void OnMouseLeftButtonUp_Click(KeyModifiers keyModifiers, ref bool handled) { // completed a click without dragging, so we're sorting - InvokeProcessSort(inputModifiers); + InvokeProcessSort(keyModifiers); handled = true; } - internal void InvokeProcessSort(InputModifiers inputModifiers) + internal void InvokeProcessSort(KeyModifiers keyModifiers) { Debug.Assert(OwningGrid != null); - if (OwningGrid.WaitForLostFocus(() => InvokeProcessSort(inputModifiers))) + if (OwningGrid.WaitForLostFocus(() => InvokeProcessSort(keyModifiers))) { return; } if (OwningGrid.CommitEdit(DataGridEditingUnit.Row, exitEditingMode: true)) { - Avalonia.Threading.Dispatcher.UIThread.Post(() => ProcessSort(inputModifiers)); + Avalonia.Threading.Dispatcher.UIThread.Post(() => ProcessSort(keyModifiers)); } } //TODO GroupSorting - internal void ProcessSort(InputModifiers inputModifiers) + internal void ProcessSort(KeyModifiers keyModifiers) { // if we can sort: // - DataConnection.AllowSort is true, and @@ -233,7 +233,7 @@ namespace Avalonia.Controls DataGridSortDescription newSort; - KeyboardHelper.GetMetaKeyState(inputModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(keyModifiers, out bool ctrl, out bool shift); DataGridSortDescription sort = OwningColumn.GetSortDescription(); IDataGridCollectionView collectionView = owningGrid.DataConnection.CollectionView; @@ -371,7 +371,7 @@ namespace Avalonia.Controls { if (_dragMode == DragMode.MouseDown) { - OnMouseLeftButtonUp_Click(args.InputModifiers, ref handled); + OnMouseLeftButtonUp_Click(args.KeyModifiers, ref handled); } else if (_dragMode == DragMode.Reorder) { diff --git a/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs b/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs index 473ddce3ad..351deceb48 100644 --- a/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs +++ b/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs @@ -9,16 +9,17 @@ namespace Avalonia.Controls.Utils { internal static class KeyboardHelper { - public static void GetMetaKeyState(InputModifiers modifiers, out bool ctrl, out bool shift) + public static void GetMetaKeyState(KeyModifiers modifiers, out bool ctrl, out bool shift) { - ctrl = (modifiers & InputModifiers.Control) == InputModifiers.Control; - shift = (modifiers & InputModifiers.Shift) == InputModifiers.Shift; + ctrl = (modifiers & KeyModifiers.Control) == KeyModifiers.Control; + shift = (modifiers & KeyModifiers.Shift) == KeyModifiers.Shift; } - public static void GetMetaKeyState(InputModifiers modifiers, out bool ctrl, out bool shift, out bool alt) + + public static void GetMetaKeyState(KeyModifiers modifiers, out bool ctrl, out bool shift, out bool alt) { - ctrl = (modifiers & InputModifiers.Control) == InputModifiers.Control; - shift = (modifiers & InputModifiers.Shift) == InputModifiers.Shift; - alt = (modifiers & InputModifiers.Alt) == InputModifiers.Alt; + ctrl = (modifiers & KeyModifiers.Control) == KeyModifiers.Control; + shift = (modifiers & KeyModifiers.Shift) == KeyModifiers.Shift; + alt = (modifiers & KeyModifiers.Alt) == KeyModifiers.Alt; } } } diff --git a/src/Avalonia.Controls/Calendar/Calendar.cs b/src/Avalonia.Controls/Calendar/Calendar.cs index 94f8ad41a0..f412cea20a 100644 --- a/src/Avalonia.Controls/Calendar/Calendar.cs +++ b/src/Avalonia.Controls/Calendar/Calendar.cs @@ -1575,7 +1575,7 @@ namespace Avalonia.Controls base.OnPointerWheelChanged(e); if (!e.Handled) { - CalendarExtensions.GetMetaKeyState(e.InputModifiers, out bool ctrl, out bool shift); + CalendarExtensions.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); if (!ctrl) { @@ -1631,7 +1631,7 @@ namespace Avalonia.Controls // Some keys (e.g. Left/Right) need to be translated in RightToLeft mode Key invariantKey = e.Key; //InteractionHelper.GetLogicalKey(FlowDirection, e.Key); - CalendarExtensions.GetMetaKeyState(e.Modifiers, out bool ctrl, out bool shift); + CalendarExtensions.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); switch (invariantKey) { diff --git a/src/Avalonia.Controls/Calendar/CalendarExtensions.cs b/src/Avalonia.Controls/Calendar/CalendarExtensions.cs index 73de1c38f3..00b5ce10bc 100644 --- a/src/Avalonia.Controls/Calendar/CalendarExtensions.cs +++ b/src/Avalonia.Controls/Calendar/CalendarExtensions.cs @@ -9,10 +9,10 @@ namespace Avalonia.Controls.Primitives { internal static class CalendarExtensions { - public static void GetMetaKeyState(InputModifiers modifiers, out bool ctrl, out bool shift) + public static void GetMetaKeyState(KeyModifiers modifiers, out bool ctrl, out bool shift) { - ctrl = (modifiers & InputModifiers.Control) == InputModifiers.Control; - shift = (modifiers & InputModifiers.Shift) == InputModifiers.Shift; + ctrl = (modifiers & KeyModifiers.Control) == KeyModifiers.Control; + shift = (modifiers & KeyModifiers.Shift) == KeyModifiers.Shift; } } } diff --git a/src/Avalonia.Controls/Calendar/CalendarItem.cs b/src/Avalonia.Controls/Calendar/CalendarItem.cs index 395196d926..d6874e1ad6 100644 --- a/src/Avalonia.Controls/Calendar/CalendarItem.cs +++ b/src/Avalonia.Controls/Calendar/CalendarItem.cs @@ -958,7 +958,7 @@ namespace Avalonia.Controls.Primitives } bool ctrl, shift; - CalendarExtensions.GetMetaKeyState(e.InputModifiers, out ctrl, out shift); + CalendarExtensions.GetMetaKeyState(e.KeyModifiers, out ctrl, out shift); CalendarDayButton b = sender as CalendarDayButton; if (b != null) diff --git a/src/Avalonia.Controls/Calendar/DatePicker.cs b/src/Avalonia.Controls/Calendar/DatePicker.cs index b4d4fed9fc..46a1f5557b 100644 --- a/src/Avalonia.Controls/Calendar/DatePicker.cs +++ b/src/Avalonia.Controls/Calendar/DatePicker.cs @@ -1008,7 +1008,7 @@ namespace Avalonia.Controls } case Key.Down: { - if ((e.Modifiers & InputModifiers.Control) == InputModifiers.Control) + if ((e.KeyModifiers & KeyModifiers.Control) == KeyModifiers.Control) { HandlePopUp(); return true; diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index c2cf20b32d..9d471a0fc0 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -130,7 +130,7 @@ namespace Avalonia.Controls return; if (e.Key == Key.F4 || - ((e.Key == Key.Down || e.Key == Key.Up) && ((e.Modifiers & InputModifiers.Alt) != 0))) + ((e.Key == Key.Down || e.Key == Key.Up) && ((e.KeyModifiers & KeyModifiers.Alt) != 0))) { IsDropDownOpen = !IsDropDownOpen; e.Handled = true; diff --git a/src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs b/src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs index 78361fcc8f..7f2008c739 100644 --- a/src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs +++ b/src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs @@ -261,7 +261,7 @@ namespace Avalonia.Controls.Utils break; case Key.Down: - if ((e.Modifiers & InputModifiers.Alt) == InputModifiers.None) + if ((e.KeyModifiers & KeyModifiers.Alt) == KeyModifiers.None) { SelectedIndexIncrement(); e.Handled = true; diff --git a/src/Avalonia.Input/KeyboardNavigationHandler.cs b/src/Avalonia.Input/KeyboardNavigationHandler.cs index 32faf98603..aef98ddff8 100644 --- a/src/Avalonia.Input/KeyboardNavigationHandler.cs +++ b/src/Avalonia.Input/KeyboardNavigationHandler.cs @@ -124,7 +124,7 @@ namespace Avalonia.Input if (current != null && e.Key == Key.Tab) { - var direction = (e.Modifiers & InputModifiers.Shift) == 0 ? + var direction = (e.KeyModifiers & KeyModifiers.Shift) == 0 ? NavigationDirection.Next : NavigationDirection.Previous; Move(current, direction, e.Modifiers); e.Handled = true; From 68177c8c70f35358696a9149f5f6dd6039c8db00 Mon Sep 17 00:00:00 2001 From: Omid Mafakher Date: Mon, 3 Feb 2020 16:12:35 +0200 Subject: [PATCH 02/10] Add Awesome-Avalonia link to about section @grokys I added to the About section. Do you think is it good place? --- readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/readme.md b/readme.md index 97c6509362..783857a096 100644 --- a/readme.md +++ b/readme.md @@ -16,6 +16,8 @@ |---|---|---| | | | | +[Awesome Avalonia](https://github.com/AvaloniaCommunity/awesome-avalonia) is curated list of awesome Avalonia UI tools, libraries, projects and resources. + ## Getting Started Avalonia [Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio) contains project and control templates that will help you get started. After installing it, open "New Project" dialog in Visual Studio, choose "Avalonia" in "Visual C#" section, select "Avalonia .NET Core Application" and press OK (screenshot). Now you can write code and markup that will work on multiple platforms! From 86531adc6945e2de1e16da3158d6e99df558ca5b Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Mon, 3 Feb 2020 10:31:34 +0200 Subject: [PATCH 03/10] fix #3500 crash after close any fullscreen window on mac --- native/Avalonia.Native/src/OSX/window.mm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 3acc5e365b..e39a061e99 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -805,7 +805,12 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent [self removeTrackingArea:_area]; _area = nullptr; } - + + if (_parent == nullptr) + { + return; + } + NSRect rect = NSZeroRect; rect.size = newSize; From 82c963eb80216c3aa5a1fbaa387411b2a9421d86 Mon Sep 17 00:00:00 2001 From: Symbai Date: Tue, 4 Feb 2020 11:57:59 +0000 Subject: [PATCH 04/10] Update Default.xaml --- src/Avalonia.Controls.DataGrid/Themes/Default.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml index 7b6870fec3..7a399349f6 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml @@ -217,12 +217,12 @@ - + - + From 4ac1fee023d3b290c6963bea7a7ef0de7cee9cc2 Mon Sep 17 00:00:00 2001 From: Symbai Date: Tue, 4 Feb 2020 12:10:23 +0000 Subject: [PATCH 05/10] Update TextBox.xaml --- src/Avalonia.Themes.Default/TextBox.xaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Avalonia.Themes.Default/TextBox.xaml b/src/Avalonia.Themes.Default/TextBox.xaml index ec1f6e9e7d..423d19da14 100644 --- a/src/Avalonia.Themes.Default/TextBox.xaml +++ b/src/Avalonia.Themes.Default/TextBox.xaml @@ -70,4 +70,7 @@ + From c428e00de76a39261bb7df45a3a7ef1e6bd0f464 Mon Sep 17 00:00:00 2001 From: Symbai Date: Tue, 4 Feb 2020 12:13:49 +0000 Subject: [PATCH 06/10] Update Default.xaml --- src/Avalonia.Controls.DataGrid/Themes/Default.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml index 7a399349f6..7b6870fec3 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml @@ -217,12 +217,12 @@ - + - + From 38e65c5a536efe961fdd20ebcf0bc8354576c568 Mon Sep 17 00:00:00 2001 From: Symbai Date: Tue, 4 Feb 2020 12:15:06 +0000 Subject: [PATCH 07/10] Update ComboBox.xaml --- src/Avalonia.Themes.Default/ComboBox.xaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Avalonia.Themes.Default/ComboBox.xaml b/src/Avalonia.Themes.Default/ComboBox.xaml index 675234c16a..1c5c8106d3 100644 --- a/src/Avalonia.Themes.Default/ComboBox.xaml +++ b/src/Avalonia.Themes.Default/ComboBox.xaml @@ -58,4 +58,7 @@ + From 7c06fc3d3d8d79c7fa1e87e3f0da1a0b9a7647c7 Mon Sep 17 00:00:00 2001 From: Symbai Date: Tue, 4 Feb 2020 12:15:34 +0000 Subject: [PATCH 08/10] Update ListBox.xaml --- src/Avalonia.Themes.Default/ListBox.xaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Themes.Default/ListBox.xaml b/src/Avalonia.Themes.Default/ListBox.xaml index 59c596bcaa..30531459df 100644 --- a/src/Avalonia.Themes.Default/ListBox.xaml +++ b/src/Avalonia.Themes.Default/ListBox.xaml @@ -7,7 +7,7 @@ - + From 5578e94177a65d6e0167da8164d4d6e9b2b8bf5b Mon Sep 17 00:00:00 2001 From: Symbai Date: Tue, 4 Feb 2020 12:30:24 +0000 Subject: [PATCH 09/10] Update Slider.xaml --- src/Avalonia.Themes.Default/Slider.xaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Themes.Default/Slider.xaml b/src/Avalonia.Themes.Default/Slider.xaml index eb46fdffa2..b21cbf3650 100644 --- a/src/Avalonia.Themes.Default/Slider.xaml +++ b/src/Avalonia.Themes.Default/Slider.xaml @@ -4,7 +4,7 @@ - + @@ -20,7 +20,7 @@ - + @@ -55,7 +55,7 @@ - + @@ -87,4 +87,7 @@ + From 0655c3d8e5eddb79eb1137e128810334df818520 Mon Sep 17 00:00:00 2001 From: Symbai Date: Tue, 4 Feb 2020 12:30:56 +0000 Subject: [PATCH 10/10] Update ListBox.xaml --- src/Avalonia.Themes.Default/ListBox.xaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Themes.Default/ListBox.xaml b/src/Avalonia.Themes.Default/ListBox.xaml index 30531459df..e91d8a6772 100644 --- a/src/Avalonia.Themes.Default/ListBox.xaml +++ b/src/Avalonia.Themes.Default/ListBox.xaml @@ -1,4 +1,5 @@ - + - +