Skip to content

Commit 4e089fd

Browse files
authored
Merge 04a6e00 into f749e49
2 parents f749e49 + 04a6e00 commit 4e089fd

4 files changed

Lines changed: 75 additions & 95 deletions

File tree

source/NVDAObjects/UIA/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -959,8 +959,8 @@ def updateCaret(self) -> None:
959959

960960

961961
class UIA(Window):
962-
_UIACustomProps = UIAHandler.customProps.CustomPropertiesCommon.get()
963-
_UIACustomAnnotationTypes = UIAHandler.customAnnotations.CustomAnnotationTypesCommon.get()
962+
_UIACustomProps = UIAHandler.customProps.CustomPropertiesCommon()
963+
_UIACustomAnnotationTypes = UIAHandler.customAnnotations.CustomAnnotationTypesCommon()
964964

965965
shouldAllowDuplicateUIAFocusEvent = False
966966

source/NVDAObjects/UIA/excel.py

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,7 @@
3333
class ExcelCustomProperties:
3434
""" UIA 'custom properties' specific to Excel.
3535
Once registered, all subsequent registrations will return the same ID value.
36-
This class should be used as a singleton via ExcelCustomProperties.get()
37-
to prevent unnecessary work by repeatedly interacting with UIA.
3836
"""
39-
#: Singleton instance
40-
_instance: "Optional[ExcelCustomProperties]" = None
41-
42-
@classmethod
43-
def get(cls) -> "ExcelCustomProperties":
44-
"""Get the singleton instance or initialise it.
45-
"""
46-
if cls._instance is None:
47-
cls._instance = cls()
48-
return cls._instance
4937

5038
def __init__(self):
5139
self.cellFormula = CustomPropertyInfo(
@@ -100,20 +88,8 @@ def __init__(self):
10088
class ExcelCustomAnnotationTypes:
10189
""" UIA 'custom annotation types' specific to Excel.
10290
Once registered, all subsequent registrations will return the same ID value.
103-
This class should be used as a singleton via ExcelCustomAnnotationTypes.get()
104-
to prevent unnecessary work by repeatedly interacting with UIA.
10591
"""
106-
#: Singleton instance
107-
_instance: "Optional[ExcelCustomAnnotationTypes]" = None
108-
109-
@classmethod
110-
def get(cls) -> "ExcelCustomAnnotationTypes":
111-
"""Get the singleton instance or initialise it.
112-
"""
113-
if cls._instance is None:
114-
cls._instance = cls()
115-
return cls._instance
116-
92+
11793
def __init__(self):
11894
# Available custom Annotations list at https://docs.microsoft.com/en-us/office/uia/excel/excelannotations
11995
# Note annotation:
@@ -127,9 +103,8 @@ def __init__(self):
127103
class ExcelObject(UIA):
128104
"""Common base class for all Excel UIA objects
129105
"""
130-
_UIAExcelCustomProps = ExcelCustomProperties.get()
131-
_UIAExcelCustomAnnotationTypes = ExcelCustomAnnotationTypes.get()
132-
106+
_UIAExcelCustomProps = ExcelCustomProperties()
107+
_UIAExcelCustomAnnotationTypes = ExcelCustomAnnotationTypes()
133108

134109

135110
class ExcelCell(ExcelObject):

source/UIAHandler/customAnnotations.py

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,8 @@
11
# A part of NonVisual Desktop Access (NVDA)
2-
# Copyright (C) 2021 NV Access Limited
2+
# Copyright (C) 2021-2022 NV Access Limited, Łukasz Golonka
33
# This file is covered by the GNU General Public License.
44
# See the file COPYING for more details.
55

6-
from dataclasses import (
7-
dataclass,
8-
field,
9-
)
10-
from typing import Optional
11-
12-
from comtypes import (
13-
GUID,
14-
byref,
15-
)
16-
import winVersion
17-
18-
196
"""
207
This module provides helpers and a common format to define UIA custom annotation types.
218
The common custom annotation types are defined here.
@@ -32,17 +19,31 @@
3219
GUID for the annotation type.
3320
"""
3421

22+
import dataclasses
23+
from typing import (
24+
ClassVar,
25+
Dict,
26+
)
27+
28+
from comtypes import (
29+
GUID,
30+
byref,
31+
)
32+
33+
import winVersion
34+
3535

36-
@dataclass
36+
@dataclasses.dataclass
3737
class CustomAnnotationTypeInfo:
3838
"""Holds information about a CustomAnnotationType
3939
This makes it easy to define custom annotation types to be loaded.
4040
"""
4141
guid: GUID
42-
id: int = field(init=False)
42+
_registeredAnnotations: ClassVar[Dict[GUID, int]] = dict()
43+
44+
def _registerCustomAnnotation(self) -> int:
45+
""" Registers the annotation with a given GUID.
4346
44-
def __post_init__(self) -> None:
45-
""" The id field must be initialised at runtime.
4647
A GUID uniquely identifies a custom annotation, but the UIA system relies on integer IDs.
4748
Any application (clients or providers) can register a custom annotation type, subsequent applications
4849
will get the same id for a given GUID.
@@ -52,29 +53,30 @@ def __post_init__(self) -> None:
5253
"""
5354
if winVersion.getWinVer() >= winVersion.WIN11:
5455
import NVDAHelper
55-
self.id = NVDAHelper.localLib.registerUIAAnnotationType(
56+
return NVDAHelper.localLib.registerUIAAnnotationType(
5657
byref(self.guid),
5758
)
58-
else:
59-
self.id = 0
59+
return 0
60+
61+
@property
62+
def id(self) -> int:
63+
"""Return an ID for a given annotation registering it first if necessary.
64+
65+
Id's of all registered annotations are cached when requested for the first time
66+
to prevent unnecessary work by repeatedly interacting with UIA .
67+
"""
68+
try:
69+
annotationId = self._registeredAnnotations[self.guid]
70+
except KeyError:
71+
annotationId = self._registerCustomAnnotation()
72+
self._registeredAnnotations[self.guid] = annotationId
73+
return annotationId
6074

6175

6276
class CustomAnnotationTypesCommon:
6377
"""UIA 'custom annotation types' common to all applications.
6478
Once registered, all subsequent registrations will return the same ID value.
65-
This class should be used as a singleton via CustomAnnotationTypesCommon.get()
66-
to prevent unnecessary work by repeatedly interacting with UIA.
6779
"""
68-
#: Singleton instance
69-
_instance: "Optional[CustomAnnotationTypesCommon]" = None
70-
71-
@classmethod
72-
def get(cls) -> "CustomAnnotationTypesCommon":
73-
"""Get the singleton instance or initialise it.
74-
"""
75-
if cls._instance is None:
76-
cls._instance = cls()
77-
return cls._instance
7880

7981
def __init__(self):
8082
# Registration of Custom annotation types used across multiple applications or frameworks should go here.

source/UIAHandler/customProps.py

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,8 @@
11
# A part of NonVisual Desktop Access (NVDA)
2-
# Copyright (C) 2021 NV Access Limited
2+
# Copyright (C) 2021-2022 NV Access Limited, Łukasz Golonka
33
# This file is covered by the GNU General Public License.
44
# See the file COPYING for more details.
55

6-
from dataclasses import (
7-
dataclass,
8-
field,
9-
)
10-
from typing import Optional
11-
12-
from comtypes import (
13-
GUID,
14-
byref,
15-
)
16-
from .constants import (
17-
UIAutomationType,
18-
)
19-
206
"""
217
This module provides helpers and a common format to define UIA custom properties.
228
The common custom properties are defined here.
@@ -33,47 +19,64 @@
3319
GUID for the property.
3420
"""
3521

22+
import dataclasses
23+
from typing import (
24+
ClassVar,
25+
Dict,
26+
)
27+
28+
from comtypes import (
29+
GUID,
30+
byref,
31+
)
32+
from .constants import (
33+
UIAutomationType,
34+
)
35+
3636

37-
@dataclass
37+
@dataclasses.dataclass
3838
class CustomPropertyInfo:
3939
"""Holds information about a CustomProperty
4040
This makes it easy to define custom properties to be loaded.
4141
"""
4242
guid: GUID
4343
programmaticName: str
4444
uiaType: UIAutomationType
45-
id: int = field(init=False)
45+
_registeredProperties: ClassVar[Dict[GUID, int]] = dict()
46+
47+
def _registerCustomProperty(self) -> int:
48+
""" Registers a custom property with a given id.
4649
47-
def __post_init__(self) -> None:
48-
""" The id field must be initialised at runtime.
4950
UIA will return the id to use when given the GUID.
5051
Any application can be first to register a custom property, subsequent applications
5152
will be given the same id.
5253
"""
5354
import NVDAHelper
54-
self.id = NVDAHelper.localLib.registerUIAProperty(
55+
return NVDAHelper.localLib.registerUIAProperty(
5556
byref(self.guid),
5657
self.programmaticName,
5758
self.uiaType
5859
)
5960

61+
@property
62+
def id(self) -> int:
63+
"""Return the integer id of the given property registering it first if necessary.
64+
65+
Id's of all registered properties are cached when requested for the first time
66+
to prevent unnecessary work by repeatedly interacting with UIA.
67+
"""
68+
try:
69+
propertyId = self._registeredProperties[self.guid]
70+
except KeyError:
71+
propertyId = self._registerCustomProperty()
72+
self._registeredProperties[self.guid] = propertyId
73+
return propertyId
74+
6075

6176
class CustomPropertiesCommon:
6277
"""UIA 'custom properties' common to all applications.
6378
Once registered, all subsequent registrations will return the same ID value.
64-
This class should be used as a singleton via CustomPropertiesCommon.get()
65-
to prevent unnecessary work by repeatedly interacting with UIA.
66-
"""
67-
#: Singleton instance
68-
_instance: "Optional[CustomPropertiesCommon]" = None
69-
70-
@classmethod
71-
def get(cls) -> "CustomPropertiesCommon":
72-
"""Get the singleton instance or initialise it.
7379
"""
74-
if cls._instance is None:
75-
cls._instance = cls()
76-
return cls._instance
7780

7881
def __init__(self):
7982

0 commit comments

Comments
 (0)