Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
K
kernel
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
af3
kernel
Merge requests
!125
4014
Code
Review changes
Check out branch
Download
Patches
Plain diff
Merged
4014
4014
into
master
Overview
6
Commits
46
Pipelines
0
Changes
55
1 unresolved thread
Hide all comments
Merged
Andreas Bayha
requested to merge
4014
into
master
4 years ago
Overview
6
Commits
46
Pipelines
0
Changes
1
1 unresolved thread
Hide all comments
Expand
Annotation View
https://af3-developer.fortiss.org/issues/4014
0
0
Merge request reports
Compare
version 5
version 18
31b575ef
4 years ago
version 17
133a7b22
4 years ago
version 16
68b88482
4 years ago
version 15
c16c2b7a
4 years ago
version 14
a39ba55d
4 years ago
version 13
184cdc06
4 years ago
version 12
49cc3011
4 years ago
version 11
59d0e98f
4 years ago
version 10
bee9f3a8
4 years ago
version 9
bbbde489
4 years ago
version 8
602b8d3f
4 years ago
version 7
f496fc6b
4 years ago
version 6
23d046ad
4 years ago
version 5
35b67747
4 years ago
version 4
2e22102d
4 years ago
version 3
156fc852
4 years ago
version 2
aa632a1e
4 years ago
version 1
5ff9d0d5
4 years ago
master (base)
and
version 6
latest version
f942d3f2
46 commits,
4 years ago
version 18
31b575ef
45 commits,
4 years ago
version 17
133a7b22
44 commits,
4 years ago
version 16
68b88482
43 commits,
4 years ago
version 15
c16c2b7a
42 commits,
4 years ago
version 14
a39ba55d
41 commits,
4 years ago
version 13
184cdc06
40 commits,
4 years ago
version 12
49cc3011
39 commits,
4 years ago
version 11
59d0e98f
38 commits,
4 years ago
version 10
bee9f3a8
37 commits,
4 years ago
version 9
bbbde489
36 commits,
4 years ago
version 8
602b8d3f
35 commits,
4 years ago
version 7
f496fc6b
34 commits,
4 years ago
version 6
23d046ad
33 commits,
4 years ago
version 5
35b67747
32 commits,
4 years ago
version 4
2e22102d
31 commits,
4 years ago
version 3
156fc852
30 commits,
4 years ago
version 2
aa632a1e
29 commits,
4 years ago
version 1
5ff9d0d5
28 commits,
4 years ago
Show latest version
1 file
+
12
−
3
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFXController.java
0 → 100644
+
494
−
0
Options
/*-------------------------------------------------------------------------+
| Copyright 2020 fortiss GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package
org.fortiss.tooling.base.ui.annotation.view.fx
;
import
static
java
.
util
.
Collections
.
emptyList
;
import
static
java
.
util
.
Collections
.
sort
;
import
static
java
.
util
.
stream
.
Collectors
.
toList
;
import
static
org
.
fortiss
.
tooling
.
base
.
ui
.
annotation
.
view
.
fx
.
FXAnnotationFilterContentProvider
.
HIERARCHY_LEVELS_ALL
;
import
static
org
.
fortiss
.
tooling
.
base
.
ui
.
annotation
.
view
.
fx
.
FXAnnotationFilterContentProvider
.
HIERARCHY_LEVELS_CURRENT
;
import
static
org
.
fortiss
.
tooling
.
base
.
ui
.
annotation
.
view
.
fx
.
FXAnnotationFilterContentProvider
.
HIERARCHY_LEVELS_SELECTED_SUBMODEL
;
import
static
org
.
fortiss
.
tooling
.
kernel
.
ui
.
util
.
SelectionUtils
.
checkAndPickFirst
;
import
static
org
.
fortiss
.
tooling
.
kernel
.
utils
.
EcoreUtils
.
getChildrenWithType
;
import
static
org
.
fortiss
.
tooling
.
kernel
.
utils
.
EcoreUtils
.
getFirstParentWithType
;
import
static
org
.
fortiss
.
tooling
.
kernel
.
utils
.
LoggingUtils
.
showWarning
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.TreeSet
;
import
org.eclipse.emf.common.util.EList
;
import
org.eclipse.emf.ecore.EClassifier
;
import
org.eclipse.emf.ecore.EEnum
;
import
org.eclipse.emf.ecore.EEnumLiteral
;
import
org.eclipse.emf.ecore.EObject
;
import
org.eclipse.jface.viewers.ISelection
;
import
org.eclipse.ui.ISelectionListener
;
import
org.eclipse.ui.IWorkbenchPart
;
import
org.fortiss.tooling.base.annotation.AnnotationEntry
;
import
org.fortiss.tooling.base.annotation.AnnotationValueService
;
import
org.fortiss.tooling.base.annotation.IAnnotationValueService
;
import
org.fortiss.tooling.base.annotation.valueprovider.EStructuralFeatureDescriptor
;
import
org.fortiss.tooling.base.annotation.valueprovider.IAnnotationValueProvider
;
import
org.fortiss.tooling.base.annotation.valueprovider.ValueProviderBase
;
import
org.fortiss.tooling.base.model.element.IAnnotatedSpecification
;
import
org.fortiss.tooling.base.model.element.IModelElement
;
import
org.fortiss.tooling.common.ui.javafx.control.treetableview.DynamicTreeTableUIProviderBase
;
import
org.fortiss.tooling.common.ui.javafx.control.treetableview.DynamicTreeTableViewer
;
import
org.fortiss.tooling.common.ui.javafx.layout.CompositeFXControllerBase
;
import
org.fortiss.tooling.kernel.extension.data.ITopLevelElement
;
import
org.fortiss.tooling.kernel.model.INamedCommentedElement
;
import
org.fortiss.tooling.kernel.model.IProjectRootElement
;
import
org.fortiss.tooling.kernel.service.IPersistencyService
;
import
com.sun.webkit.ThemeClient
;
import
javafx.collections.ObservableList
;
import
javafx.fxml.FXML
;
import
javafx.scene.Node
;
import
javafx.scene.control.CheckBox
;
import
javafx.scene.control.ComboBox
;
import
javafx.scene.control.RadioButton
;
import
javafx.scene.control.SplitPane
;
import
javafx.scene.control.TextField
;
import
javafx.scene.control.TreeTableColumn
;
import
javafx.scene.control.TreeTableView
;
/**
* Controller for the Annotations view.
*
* @author bayha
*/
@SuppressWarnings
(
"unchecked"
)
public
class
AnnotationViewFXController
extends
CompositeFXControllerBase
<
SplitPane
,
Node
>
implements
ISelectionListener
{
/** Option text for the annotation type filter combo box. */
private
static
final
String
SHOW_ALL_ANNOTATION_TYPES
=
"Show all annotation types"
;
/** {@link TextField} for entering the filter pattern. */
@FXML
private
TextField
txtFilterText
;
/** {@link RadioButton} to enable filtering for model element names. */
@FXML
private
RadioButton
radBtnFilterModelElements
;
/** {@link RadioButton} to enable filtering for annotation names. */
@FXML
private
RadioButton
radBtnFilterAnnotationNames
;
/** {@link CheckBox} to make name filtering case sensitive. */
@FXML
private
CheckBox
chkBoxMatchCase
;
/** {@link CheckBox} to only show model elements with the same type as the selected one. */
@FXML
private
CheckBox
chkBoxselectedTypeOnly
;
/**
* {@link ComboBox} to chose the hierarchy option according to which the model elements are
* displayed.
*/
@FXML
private
ComboBox
<
String
>
comboHierarchy
;
/** {@link ComboBox} to chose an annotation type to be displayed exclusively. */
@FXML
private
ComboBox
<
String
>
comboAnnotationType
;
/** The {@link TreeTableView} for the annotation table. */
@FXML
private
TreeTableView
<
AnnotationEntry
>
annotationTreeTableView
;
/** The {@link DynamicTreeTableViewer} to manage the annotationTreeTableView. */
private
DynamicTreeTableViewer
<
AnnotationEntry
>
annotationViewer
;
/** The {@link IProjectRootElement} in which the selected element is contained in. */
private
IProjectRootElement
curentRootElement
;
/** {@link Set} of {@link ColumnHandle}s (i.e. management objects for columns). */
private
Set
<
ColumnHandle
<
IAnnotatedSpecification
>>
columnHandles
=
new
TreeSet
<>();
/**
* {@link Map} that maps {@link ColumnHandle}s (i.e. management objects for columns) to the
* respective columns.
*/
private
Map
<
ColumnHandle
<
IAnnotatedSpecification
>,
TreeTableColumn
<
AnnotationEntry
,
?>>
columnHandleToColumn
=
new
HashMap
<
ColumnHandle
<
IAnnotatedSpecification
>,
TreeTableColumn
<
AnnotationEntry
,
?>>();
/** {@link Map} to get the {@link IAnnotatedSpecification} that corresponds to a column name. */
private
Map
<
String
,
IAnnotatedSpecification
>
colNameToSpecification
=
new
HashMap
<
String
,
IAnnotatedSpecification
>();
/** Content provider for the annotation table with all filtering functionality. */
private
final
FXAnnotationFilterContentProvider
filterContentProvider
=
new
FXAnnotationFilterContentProvider
();
/**
* Associates the handles of the annotations with their ordered column indexes.
* Used for the UI providers of cell items.
*/
/* package */
Map
<
Integer
,
ColumnHandle
<
IAnnotatedSpecification
>>
colIdxAnnotationMap
=
new
HashMap
<>();
/**
* Root element to be added to the tree viewer (but not displayed). Container for all
* {@link AnnotationEntry}s.
*/
/* package */
ArtificialRoot
root
=
new
ArtificialRoot
();
/** The {@link IModelElement} that is currently selected by the user. */
/* package */
IModelElement
selected
;
/** {@inheritDoc} */
@Override
public
String
getFXMLLocation
()
{
return
"AnnotationViewFx.fxml"
;
}
/** {@inheritDoc} */
@Override
public
void
initialize
()
{
setupFilterWidgets
();
}
/** {@inheritDoc} */
@Override
public
void
selectionChanged
(
IWorkbenchPart
part
,
ISelection
selection
)
{
EObject
selected
=
checkAndPickFirst
(
selection
,
EObject
.
class
);
if
(
selected
==
null
)
{
clearTableViewer
();
return
;
}
if
(
selected
instanceof
IProjectRootElement
)
{
curentRootElement
=
(
IProjectRootElement
)
selected
;
}
else
{
curentRootElement
=
getFirstParentWithType
(
selected
,
IProjectRootElement
.
class
);
}
if
(
curentRootElement
==
null
)
{
// There was no root element for the selected element. (Usually should be the
// FileProject.) This is not displayed here.
clearTableViewer
();
return
;
}
if
(
selected
instanceof
IModelElement
)
{
filterContentProvider
.
setCurrentySelectedModelElement
((
IModelElement
)
selected
);
this
.
selected
=
(
IModelElement
)
selected
;
}
setupAnnotationTree
();
// After the ColumHandles are created in setupAnnotationTree(), we can fill the
// corresponding filter combo.
ObservableList
<
String
>
annotationTypeOptions
=
comboAnnotationType
.
getItems
();
annotationTypeOptions
.
clear
();
annotationTypeOptions
.
add
(
SHOW_ALL_ANNOTATION_TYPES
);
List
<
String
>
annotations
=
columnHandles
.
stream
().
map
(
h
->
h
.
getColumnName
()).
collect
(
toList
());
annotationTypeOptions
.
addAll
(
annotations
);
comboAnnotationType
.
setValue
(
SHOW_ALL_ANNOTATION_TYPES
);
}
/**
* Generates / restructures the annotation tree according to the currently
* selectedElement.
*/
private
void
setupAnnotationTree
()
{
if
(
curentRootElement
==
null
)
{
return
;
}
clearTableViewer
();
// Collect the annotation entries for all elements.
EList
<
IModelElement
>
listElements
=
getChildrenWithType
(
curentRootElement
,
IModelElement
.
class
);
if
(
curentRootElement
instanceof
IModelElement
)
{
listElements
.
add
((
IModelElement
)
curentRootElement
);
}
root
=
new
ArtificialRoot
();
for
(
IModelElement
elem
:
listElements
)
{
AnnotationEntry
entry
=
IAnnotationValueService
.
getInstance
().
getAnnotationEntry
(
elem
);
if
(
entry
!=
null
&&
!
entry
.
getSpecificationsList
().
isEmpty
())
{
root
.
elements
.
add
(
entry
);
}
}
sort
(
root
.
elements
);
Set
<
AnnotationEntry
>
annotationEntries
=
new
HashSet
<>();
listElements
.
forEach
(
e
->
annotationEntries
.
add
(
AnnotationValueService
.
getInstance
().
getAnnotationEntry
(
e
)));
// Aggregate required columns. Column order is defined by
// ColumnHandle.compareTo().
for
(
AnnotationEntry
entry
:
annotationEntries
)
{
for
(
IAnnotatedSpecification
spec
:
entry
.
getSpecificationsList
())
{
ColumnHandle
<
IAnnotatedSpecification
>
columnHandle
=
new
ColumnHandle
<
IAnnotatedSpecification
>(
entry
,
spec
);
columnHandles
.
add
(
columnHandle
);
colNameToSpecification
.
put
(
columnHandle
.
getColumnName
(),
spec
);
}
}
// The DynamicTreeTableViewer needs to be created new, as the root is different.
boolean
showRoot
=
false
;
int
revealLevel
=
1
;
DynamicTreeTableUIProviderBase
<
AnnotationEntry
>
uiProvider
=
new
AnnotationTreeTableUIProvider
(
this
);
annotationViewer
=
new
DynamicTreeTableViewer
<
AnnotationEntry
>(
annotationTreeTableView
,
root
,
showRoot
,
revealLevel
,
filterContentProvider
,
uiProvider
);
annotationViewer
.
addColumn
(
"Model Element"
,
200
);
annotationViewer
.
addColumn
(
"Comment"
,
250
);
int
columnIdx
=
2
;
for
(
ColumnHandle
<
IAnnotatedSpecification
>
handle
:
columnHandles
)
{
TreeTableColumn
<
AnnotationEntry
,
?>
col
=
createColumnForHandle
(
columnIdx
,
handle
);
columnHandleToColumn
.
put
(
handle
,
col
);
columnIdx
++;
}
filterColumns
();
}
/** Resets {@link ThemeClient} annotation table to be empty. Also removes the columns. */
private
void
clearTableViewer
()
{
colIdxAnnotationMap
.
clear
();
columnHandles
.
clear
();
columnHandleToColumn
.
clear
();
annotationTreeTableView
.
getColumns
().
clear
();
}
/** Configures the filter widgets for the annotation table. */
private
void
setupFilterWidgets
()
{
comboAnnotationType
.
getItems
().
add
(
SHOW_ALL_ANNOTATION_TYPES
);
comboAnnotationType
.
setValue
(
SHOW_ALL_ANNOTATION_TYPES
);
ObservableList
<
String
>
hierarchyLevels
=
comboHierarchy
.
getItems
();
hierarchyLevels
.
clear
();
hierarchyLevels
.
add
(
HIERARCHY_LEVELS_ALL
);
hierarchyLevels
.
add
(
HIERARCHY_LEVELS_CURRENT
);
hierarchyLevels
.
add
(
HIERARCHY_LEVELS_SELECTED_SUBMODEL
);
comboHierarchy
.
setValue
(
HIERARCHY_LEVELS_ALL
);
comboHierarchy
.
valueProperty
().
addListener
((
obs
,
oVal
,
nVal
)
->
{
filterContentProvider
.
setHierarchyLevelFilter
(
nVal
);
updateAnnotationTree
();
});
txtFilterText
.
textProperty
().
addListener
((
obs
,
oVal
,
nVal
)
->
{
filterContentProvider
.
setFilterExpression
(
nVal
);
if
(
radBtnFilterAnnotationNames
.
isSelected
())
{
filterColumns
();
}
updateAnnotationTree
();
});
radBtnFilterAnnotationNames
.
selectedProperty
().
addListener
((
obs
,
oVal
,
nVal
)
->
{
filterContentProvider
.
setFilterColumnName
(
nVal
);
filterColumns
();
if
(
nVal
)
{
// De-select other radio button, if this one is selected.
radBtnFilterModelElements
.
setSelected
(
false
);
}
updateAnnotationTree
();
});
radBtnFilterModelElements
.
selectedProperty
().
addListener
((
obs
,
oVal
,
nVal
)
->
{
filterContentProvider
.
setFilterRowName
(
nVal
);
if
(
nVal
)
{
// De-select other radio button, if this one is selected.
radBtnFilterAnnotationNames
.
setSelected
(
false
);
}
updateAnnotationTree
();
});
chkBoxMatchCase
.
selectedProperty
().
addListener
((
obs
,
oVal
,
nVal
)
->
{
filterContentProvider
.
setFilterNameMatchCase
(
nVal
);
if
(
radBtnFilterAnnotationNames
.
isSelected
())
{
filterColumns
();
}
updateAnnotationTree
();
});
chkBoxselectedTypeOnly
.
selectedProperty
().
addListener
((
obs
,
oVal
,
nVal
)
->
{
filterContentProvider
.
setRestrictToSelectedModelElementType
(
nVal
);
updateAnnotationTree
();
});
comboAnnotationType
.
valueProperty
().
addListener
((
obs
,
oVal
,
nVal
)
->
{
IAnnotatedSpecification
selectedSpec
=
colNameToSpecification
.
get
(
nVal
);
if
(
selectedSpec
!=
null
)
{
filterContentProvider
.
setAnnotationTypeFilter
(
selectedSpec
.
getClass
());
}
else
{
// In this case, the filter has been reset to "All Types"
filterContentProvider
.
setAnnotationTypeFilter
(
null
);
}
filterColumns
();
updateAnnotationTree
();
});
}
/**
* Triggers the update the annotation tree with the latest filter settings and model element
* changes.
*/
private
void
updateAnnotationTree
()
{
annotationViewer
.
update
();
annotationViewer
.
expandAllItems
();
}
/** Hides columns which are de-selected by the current filter settings. */
private
void
filterColumns
()
{
for
(
ColumnHandle
<
IAnnotatedSpecification
>
c
:
columnHandles
)
{
TreeTableColumn
<
AnnotationEntry
,
?>
col
=
columnHandleToColumn
.
get
(
c
);
col
.
setVisible
(
filterContentProvider
.
passesColumnFilter
(
c
));
}
updateAnnotationTree
();
}
/** Creates the annotation column for the given handle. */
private
TreeTableColumn
<
AnnotationEntry
,
?>
createColumnForHandle
(
int
columnIdx
,
ColumnHandle
<
IAnnotatedSpecification
>
handle
)
{
Class
<
IAnnotatedSpecification
>
annotationClass
=
(
Class
<
IAnnotatedSpecification
>)
handle
.
getAnnotatedSpecification
().
getClass
();
AnnotationEntry
entry
=
handle
.
getEntry
();
IAnnotationValueProvider
<
IAnnotatedSpecification
>
valueProvider
=
entry
.
getAnnotationValueProvider
(
annotationClass
);
IAnnotatedSpecification
specification
=
entry
.
getSpecification
(
annotationClass
);
EClassifier
valueType
=
valueProvider
.
getEStructuralFeatureDescriptor
().
getEType
(
specification
);
String
columnName
=
valueProvider
.
getAnnotationName
(
specification
);
colIdxAnnotationMap
.
put
(
columnIdx
,
handle
);
TreeTableColumn
<
AnnotationEntry
,
?>
column
=
null
;
// Case distinction for the cell factory depending on the type to be edited.
if
(
valueType
==
null
)
{
column
=
annotationViewer
.
addColumn
(
columnName
,
150
);
column
.
setEditable
(
false
);
return
column
;
}
if
(
valueType
instanceof
EEnum
)
{
// Add a combo column for enumerations.
column
=
annotationViewer
.
addComboColumn
(
columnName
,
150
,
rowEntry
->
{
ValueProviderBase
<
IAnnotatedSpecification
>
annotationValueProvider
=
(
ValueProviderBase
<
IAnnotatedSpecification
>)
rowEntry
.
getAnnotationValueProvider
(
annotationClass
);
EStructuralFeatureDescriptor
structuralFeature
=
annotationValueProvider
.
getEStructuralFeatureDescriptor
();
EClassifier
type
=
structuralFeature
.
getEType
(
rowEntry
.
getSpecification
(
annotationClass
));
// Get the enum literals again, as it might be different for each row.
if
(
type
instanceof
EEnum
)
{
EList
<
EEnumLiteral
>
allLiterals
=
((
EEnum
)
type
).
getELiterals
();
return
allLiterals
.
stream
().
map
(
l
->
l
.
getLiteral
()).
collect
(
toList
());
}
return
emptyList
();
});
}
else
if
(
valueType
.
getInstanceClass
().
equals
(
Boolean
.
class
))
{
// Use a checkbox column for booleans
column
=
annotationViewer
.
addCheckboxColumn
(
columnName
,
100
);
}
else
{
// For all other types, there is text editing.
column
=
annotationViewer
.
addTextColumn
(
columnName
,
150
);
}
if
(
column
!=
null
)
{
column
.
setEditable
(
true
);
}
return
column
;
}
/**
* Local helper to set the given newValue for the given annotationEntry and
* specification.
*/
void
setAnnotationEntryValue
(
IAnnotatedSpecification
specification
,
AnnotationEntry
annotationEntry
,
String
newValue
)
{
ITopLevelElement
tle
=
IPersistencyService
.
getInstance
().
getTopLevelElementFor
(
curentRootElement
);
tle
.
runAsCommand
(()
->
{
try
{
annotationEntry
.
setSpecificationValue
(
newValue
,
specification
.
getClass
());
}
catch
(
Exception
e1
)
{
showWarning
(
"Problem during setting an AnnotationValue: \n"
+
e1
.
getStackTrace
());
}
});
}
/** Retrieves the model element name to be displayed for the given {@link AnnotationEntry}. */
String
getNameForAnnotationEntry
(
AnnotationEntry
entry
)
{
IModelElement
modelElement
=
entry
.
getModelElement
();
if
(
modelElement
instanceof
INamedCommentedElement
)
{
return
((
INamedCommentedElement
)
modelElement
).
getName
();
}
return
""
;
}
/**
* Local class to represent the invisible root for the tree table.
*
* The only thing relevant here, is the {@link List} 'elements'.
*/
protected
final
class
ArtificialRoot
extends
AnnotationEntry
{
/**
* Constructor.
*/
public
ArtificialRoot
()
{
super
(
selected
);
}
/** The list of {@link AnnotationEntry}s to be displayed. */
List
<
AnnotationEntry
>
elements
=
new
ArrayList
<
AnnotationEntry
>();
}
}
Loading