-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
SelectLocationController.groovy
164 lines (130 loc) · 6 KB
/
SelectLocationController.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
* Copyright (c) 2008-2015 Emmanuel Dupuy
* This program is made available under the terms of the GPLv3 License.
*/
package org.jd.gui.controller
import groovy.swing.SwingBuilder
import org.jd.gui.api.API
import org.jd.gui.api.model.Container
import org.jd.gui.model.configuration.Configuration
import org.jd.gui.model.container.FilteredContainerWrapper
import org.jd.gui.service.type.TypeFactoryService
import org.jd.gui.view.SelectLocationView
import java.awt.Point
class SelectLocationController {
API api
SelectLocationView selectLocationView
SelectLocationController(SwingBuilder swing, Configuration configuration, API api) {
this.api = api
// Create UI
selectLocationView = new SelectLocationView(swing, configuration, api)
}
void show(Point location, Collection<Container.Entry> entries, Closure locationSelectedClosure, Closure closeClosure) {
// Show UI
def map = [:].withDefault { [] }
for (def entry : entries) {
def container = entry.container
// Search root container
while (true) {
def parentContainer = container.root.parent.container
if (parentContainer.root == null) {
break
} else {
container = parentContainer
}
}
map[container].add(entry)
}
def filteredContainerWrappers = new HashSet<FilteredContainerWrapper>()
for (def mapEntry : map.entrySet()) {
def container = mapEntry.key
def parentEntry = container.root.parent
// Dummy parent entry wrapper
def parentEntryWrapper = new Container.Entry() {
Collection<Container.Entry> children
Container getContainer() { parentEntry.container }
Container.Entry getParent() { null }
URI getUri() { parentEntry.uri }
String getPath() { parentEntry.path }
boolean isDirectory() { parentEntry.isDirectory() }
long length() { parentEntry.length() }
InputStream getInputStream() { parentEntry.inputStream }
Collection<Container.Entry> getChildren() { children }
}
// Create a filtered container
// TODO In a future release, display matching types and inner-types, not only matching files
def outerEntries = getOuterEntries(mapEntry.value)
def containerWrapper = new FilteredContainerWrapper(container, parentEntryWrapper, outerEntries)
// Initialization of 'children' of dummy parent entry wrapper
parentEntryWrapper.children = containerWrapper.root.children
filteredContainerWrappers.add(containerWrapper)
}
selectLocationView.show(
location, filteredContainerWrappers, entries.size(),
{ uri -> onLocationSelected(filteredContainerWrappers, uri, locationSelectedClosure) },
closeClosure)
}
Collection<Container.Entry> getOuterEntries(Collection<Container.Entry> entries) {
def innerTypeEntryToOuterTypeEntry = [:]
def outerEntriesSet = new HashSet<Container.Entry>()
for (def entry : entries) {
def type = TypeFactoryService.instance.get(entry)?.make(api, entry, null)
if (type?.outerName) {
def outerTypeEntry = innerTypeEntryToOuterTypeEntry.get(entry)
if (outerTypeEntry == null) {
def typeNameToEntry = [:]
def innerTypeNameToOuterTypeName = [:]
// Populate "typeNameToEntry" and "innerTypeNameToOuterTypeName"
for (def e : entry.parent.children) {
type = TypeFactoryService.instance.get(e)?.make(api, e, null)
if (type) {
typeNameToEntry.put(type.name, e)
if (type.outerName) {
innerTypeNameToOuterTypeName.put(type.name, type.outerName)
}
}
}
// Search outer type entries and populate "innerTypeEntryToOuterTypeEntry"
for (def e : innerTypeNameToOuterTypeName.entrySet()) {
def innerTypeEntry = typeNameToEntry.get(e.key)
if (innerTypeEntry) {
def outerTypeName = e.value
for (;;) {
def typeName = innerTypeNameToOuterTypeName.get(outerTypeName)
if (typeName) {
outerTypeName = typeName
} else {
break
}
}
outerTypeEntry = typeNameToEntry.get(outerTypeName)
if (outerTypeEntry) {
innerTypeEntryToOuterTypeEntry.put(innerTypeEntry, outerTypeEntry)
}
}
}
// Get outer type entry
outerTypeEntry = innerTypeEntryToOuterTypeEntry.get(entry) ?: entry
}
outerEntriesSet.add(outerTypeEntry)
} else {
outerEntriesSet.add(entry)
}
}
// Return outer type entries sorted by path
return outerEntriesSet.sort { e1, e2 -> e1.path.compareTo(e2.path) }
}
void onLocationSelected(Set<FilteredContainerWrapper> filteredContainerWrappers, URI uri, Closure locationSelectedClosure) {
// Open the single entry uri
def entry = null
for (def container : filteredContainerWrappers) {
entry = container.getEntry(uri)
if (entry) {
break
}
}
if (entry) {
locationSelectedClosure(entry)
}
}
}