Skip to content

Commit

Permalink
Merge branch 'feature-issue138' #138
Browse files Browse the repository at this point in the history
* feature-issue138:
  * Fixed issue #138: Restrict the context menu to appear only when the Shift key is held down. #138
  Updated documentation for attribute `keyboard` of Visibility/Validity elements. #138
  Implemented unit tests for attribute `keyboard` of Visibility/Validity elements. #138
  * Move IKeyboardService enums to Enums.h * Rename `IKeyboardService::IsStateOn()` to `IsToggleStateOn()`. * Add `Windows` prefix to KeyboardService class. #138
  Renamed KEYB_TOGGLE_ID enumerations with KTID_ prefix to match their enum name. #138
  Implemented attribute `keyboard` validator parsing. #138
  Created IKeyboardService interface and implemented a win32 KeyboardService. #138
  • Loading branch information
end2endzone committed Jan 19, 2024
2 parents 277ca50 + 113ad3d commit cfdb368
Show file tree
Hide file tree
Showing 26 changed files with 965 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Changes for 0.9.0
* Fixed issue #134: Set a property value from a registry key.
* Fixed issue #135: Set a property value from a search in the PATH environment variable.
* Fixed issue #137: Library independent logging support.
* Fixed issue #138: Restrict the context menu to appear only when the Shift key is held down.
* Fixed issue #139: Wait for an <exec> action to complete before executing the next action.
* Fixed issue #141: Separator visibility options.
* Fixed issue #147: Allow property action attributes to not fail (continue to next action) if unresolved.
Expand Down
43 changes: 30 additions & 13 deletions UserManual.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This manual includes a description of the system functionalities and capabilitie
* [istrue attribute](#istrue-attribute)
* [isfalse attribute](#isfalse-attribute)
* [isempty attribute](#isempty-attribute)
* [keyboard attribute](#keyboard-attribute)
* [inverse attribute](#inverse-attribute)
* [Combining multiple &lt;visibility&gt; and &lt;validity&gt; elements](#combining-multiple-visibility-and-validity-elements)
* [Icons](#icons)
Expand Down Expand Up @@ -521,6 +522,21 @@ For example, the following set a menu visible only when the property `first_sele



### keyboard attribute: ###

The `keyboard` attribute validates a menu if the specified keyboard modifier (key) is pressed. A keyboard modifier is any of the following text values: `CTRL`, `ALT`, `SHIFT`. These values are not case sensitive.

If the `keyboard` attribute is set, the application will look if the matching keyboard key is pressed. If there is a match between the value and the modifier state, the validation is successful. To specify multiple modifier, one must separate each property with the `;` character. If multiple modifier are specified, **all modifier** must match the keyboard state for the validation to be successful.

If `keyboard` attribute is not specified, then the validation is successful.

For example, the following set a menu visible only when the keyboard _shift_ modifier is pressed:
```xml
<visibility keyboard="shift" />
```



### inverse attribute: ###

The `inverse` attribute inverts the logic of one or multiple attributes. For example, to inverse the meaning of the `maxfiles` attribute, set `inverse` attribute to the value `maxfiles`.
Expand All @@ -531,19 +547,20 @@ If `inverse` attribute is not specified, then the validation is successful.

The meaning of each inversed attribute in explained in the following table:

| Attributes | Meaning |
|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| class | Validates a menu if the selected file or directory **does not** match the class of the selected files.<br>If multiple classes are specified, **no classes** must match the selected files for the validation to be successful. |
| maxfiles | Defines a minimum number of selected files. Validates a menu if **more than** _x_ files are selected.<br>If 'maxfiles` is set to 5, _more than_ 5 files must be selected for the validation to be successful. |
| maxfolders | Defines a minimum number of selected folder. Validates a menu if **more than** _x_ folders are selected.<br>If 'maxfolders` is set to 3, _more than_ 3 directories must be selected for the validation to be successful. |
| fileextensions | Validates a menu if the given file's extension **does not** match the file extension selected by the user.<br>If multiple file extensions are specified, **no extension** must match the selected files for the validation to be successful. |
| pattern | Validates a menu if the selected file or directory **does not** match the wildcard pattern matching algorithm.<br>If multiple patterns are specified, **no pattern** must match the selected files for the validation to be successful. |
| exists | Validates a menu if the selected file or directory **does not** exists.<br>If multiple files/directories are specified, **all values** must _not exists_ on the system for the validation to be successful. |
| properties | Validates a menu if the specified property is **empty** or **not defined**.<br>If multiple properties are specified, **all properties** must be _empty_ or _not defined_ for the validation to be successful. |
| exprtk | Validates a menu if the given string expression **does not** evaluates to logical _true_.<br>If multiple expressions are specified, **no expression** must evaluate to logical _true_ for the validation to be successful. |
| istrue | Validates a menu if the given value **does not** evaluates to logical _true_.<br>If multiple values are specified, **no value** must evaluate to logical _true_ for the validation to be successful. |
| isfalse | Validates a menu if the given value **does not** evaluates to logical _false_.<br>If multiple values are specified, **no value** must evaluate to logical _false_ for the validation to be successful. |
| isempty | Validates a menu if the given text **is not** empty. If the attribute is not specified, then the validation is successful. Otherwise, if text is specified, the expanded value **must not** be empty. |
| Attributes | Meaning | |
|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---|
| class | Validates a menu if the selected file or directory **does not** match the class of the selected files.<br>If multiple classes are specified, **no classes** must match the selected files for the validation to be successful. | |
| maxfiles | Defines a minimum number of selected files. Validates a menu if **more than** _x_ files are selected.<br>If 'maxfiles` is set to 5, _more than_ 5 files must be selected for the validation to be successful. | |
| maxfolders | Defines a minimum number of selected folder. Validates a menu if **more than** _x_ folders are selected.<br>If 'maxfolders` is set to 3, _more than_ 3 directories must be selected for the validation to be successful. | |
| fileextensions | Validates a menu if the given file's extension **does not** match the file extension selected by the user.<br>If multiple file extensions are specified, **no extension** must match the selected files for the validation to be successful. | |
| pattern | Validates a menu if the selected file or directory **does not** match the wildcard pattern matching algorithm.<br>If multiple patterns are specified, **no pattern** must match the selected files for the validation to be successful. | |
| exists | Validates a menu if the selected file or directory **does not** exists.<br>If multiple files/directories are specified, **all values** must _not exists_ on the system for the validation to be successful. | |
| properties | Validates a menu if the specified property is **empty** or **not defined**.<br>If multiple properties are specified, **all properties** must be _empty_ or _not defined_ for the validation to be successful. | |
| exprtk | Validates a menu if the given string expression **does not** evaluates to logical _true_.<br>If multiple expressions are specified, **no expression** must evaluate to logical _true_ for the validation to be successful. | |
| istrue | Validates a menu if the given value **does not** evaluates to logical _true_.<br>If multiple values are specified, **no value** must evaluate to logical _true_ for the validation to be successful. | |
| isfalse | Validates a menu if the given value **does not** evaluates to logical _false_.<br>If multiple values are specified, **no value** must evaluate to logical _false_ for the validation to be successful. | |
| isempty | Validates a menu if the given text **is not** empty. If the attribute is not specified, then the validation is successful. Otherwise, if text is specified, the expanded value **must not** be empty. | |
| keyboard | Validates a menu if the specified keyboard modifier **is not** pressed.<br>If multiple modifiers are specified, **all modifiers** must not match the keyboard state for the validation to be successful. | |

Typical use case of the `inverse` attribute is about filtering out known file extensions.

Expand Down
14 changes: 13 additions & 1 deletion src/core/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ namespace shellanything
App::App() :
mLogger(NULL),
mRegistry(NULL),
mClipboard(NULL)
mClipboard(NULL),
mKeyboard(NULL)
{
}

Expand Down Expand Up @@ -83,6 +84,7 @@ namespace shellanything
mLogger = NULL;
mRegistry = NULL;
mClipboard = NULL;
mKeyboard = NULL;
}

void App::SetLoggerService(ILoggerService* logger)
Expand Down Expand Up @@ -115,6 +117,16 @@ namespace shellanything
return mClipboard;
}

void App::SetKeyboardService(IKeyboardService* instance)
{
mKeyboard = instance;
}

IKeyboardService* App::GetKeyboardService()
{
return mKeyboard;
}

bool App::IsTestingEnvironment()
{
std::string process_path = ra::process::GetCurrentProcessPath();
Expand Down
17 changes: 17 additions & 0 deletions src/core/App.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "ILoggerService.h"
#include "IRegistryService.h"
#include "IClipboardService.h"
#include "IKeyboardService.h"

#include <string>

Expand Down Expand Up @@ -112,6 +113,21 @@ namespace shellanything
/// <returns>Returns a pointer of the instance that is currently set. Returns NULL if no service is set.</returns>
IClipboardService* GetClipboardService();

/// <summary>
/// Set the current application keyboard service.
/// </summary>
/// <remarks>
/// If a service instance is already set, the caller must properly destroy the old instance.
/// </remarks>
/// <param name="instance">A valid instance of a the service.</param>
void SetKeyboardService(IKeyboardService* instance);

/// <summary>
/// Get the current application keyboard service.
/// </summary>
/// <returns>Returns a pointer of the instance that is currently set. Returns NULL if no service is set.</returns>
IKeyboardService* GetKeyboardService();

/// <summary>
/// Test if application is loaded in a test environment (main's tests executable).
/// </summary>
Expand Down Expand Up @@ -165,6 +181,7 @@ namespace shellanything
ILoggerService * mLogger;
IRegistryService* mRegistry;
IClipboardService* mClipboard;
IKeyboardService* mKeyboard;
};


Expand Down
4 changes: 4 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ set(SHELLANYTHING_CORE_HEADER_FILES ""
${CMAKE_SOURCE_DIR}/src/core/SelectionContext.h
${CMAKE_SOURCE_DIR}/src/core/DefaultSettings.h
${CMAKE_SOURCE_DIR}/src/core/Icon.h
${CMAKE_SOURCE_DIR}/src/core/IKeyboardService.h
${CMAKE_SOURCE_DIR}/src/core/ILiveProperty.h
${CMAKE_SOURCE_DIR}/src/core/IClipboardService.h
${CMAKE_SOURCE_DIR}/src/core/ILoggerService.h
${CMAKE_SOURCE_DIR}/src/core/IRegistryService.h
${CMAKE_SOURCE_DIR}/src/core/KeyboardHelper.h
${CMAKE_SOURCE_DIR}/src/core/LoggerHelper.h
${CMAKE_SOURCE_DIR}/src/core/Menu.h
${CMAKE_SOURCE_DIR}/src/core/Validator.h
Expand Down Expand Up @@ -54,10 +56,12 @@ add_library(sa.core SHARED
IAttributeValidator.h
IAttributeValidator.cpp
Icon.cpp
IKeyboardService.cpp
ILiveProperty.cpp
IClipboardService.cpp
ILoggerService.cpp
IRegistryService.cpp
KeyboardHelper.cpp
LoggerHelper.cpp
InputBox.h
InputBox.cpp
Expand Down
16 changes: 16 additions & 0 deletions src/core/Enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ namespace shellanything
FIND_BY_NAME_ALL = (-1),
};

enum KEYB_MODIFIER_ID
{
KMID_INVALID = 0,
KMID_CTRL,
KMID_ALT,
KMID_SHIFT,
};

enum KEYB_TOGGLE_ID
{
KTID_INVALID = 0,
KTID_CAPS_LOCK,
KTID_SCROLL_LOCK,
KTID_NUM_LOCK,
};

} //namespace shellanything

#endif //SA_ENUMS_H
38 changes: 38 additions & 0 deletions src/core/IKeyboardService.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**********************************************************************************
* MIT License
*
* Copyright (c) 2018 Antoine Beauchamp
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*********************************************************************************/

#include "IKeyboardService.h"

namespace shellanything
{

IKeyboardService::IKeyboardService()
{
}

IKeyboardService::~IKeyboardService()
{
}

} //namespace shellanything
84 changes: 84 additions & 0 deletions src/core/IKeyboardService.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**********************************************************************************
* MIT License
*
* Copyright (c) 2018 Antoine Beauchamp
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*********************************************************************************/

#ifndef SA_IKEYBOARD_SERVICE_H
#define SA_IKEYBOARD_SERVICE_H

#include "shellanything/export.h"
#include "shellanything/config.h"
#include "Enums.h"

#include <string>

namespace shellanything
{
/// <summary>
/// Abstract keyboard service class.
/// Used to decouple the core from Windows Operating System API.
/// </summary>
class SHELLANYTHING_EXPORT IKeyboardService
{
public:
IKeyboardService();
virtual ~IKeyboardService();

private:
// Disable and copy constructor, dtor and copy operator
IKeyboardService(const IKeyboardService&);
IKeyboardService& operator=(const IKeyboardService&);
public:

/// <summary>
/// Reads the state of a keyboard modifier key.
/// </summary>
/// <param name="key">The id of a matching keyboard modifier key.</param>
/// <returns>Returns true if the given key is UP. Returns false otherwise.</returns>
virtual bool IsModifierKeyUp(KEYB_MODIFIER_ID key) const = 0;

/// <summary>
/// Reads the state of a keyboard modifier key.
/// </summary>
/// <param name="key">The id of a matching keyboard modifier key.</param>
/// <returns>Returns true if the given key is DOWN. Returns false otherwise.</returns>
virtual bool IsModifierKeyDown(KEYB_MODIFIER_ID key) const = 0;

/// <summary>
/// Reads the state of a keyboard toggle key.
/// </summary>
/// <param name="key">The id of a matching keyboard toggle key.</param>
/// <returns>Returns true if the given key is ON. Returns false otherwise.</returns>
virtual bool IsToggleStateOn(KEYB_TOGGLE_ID state) const = 0;

/// <summary>
/// Reads the state of a keyboard toggle key.
/// </summary>
/// <param name="key">The id of a matching keyboard toggle key.</param>
/// <returns>Returns true if the given key is OFF. Returns false otherwise.</returns>
virtual bool IsToggleStateOff(KEYB_TOGGLE_ID state) const = 0;

};

} //namespace shellanything

#endif //SA_IKEYBOARD_SERVICE_H
Loading

0 comments on commit cfdb368

Please sign in to comment.