-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
40 changed files
with
8,756 additions
and
6,102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
annis-gui/src/main/java/annis/gui/components/IframeState.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright 2014 Corpuslinguistic working group Humboldt University Berlin. | ||
* | ||
* 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 annis.gui.components; | ||
|
||
import com.vaadin.shared.ui.JavaScriptComponentState; | ||
|
||
/** | ||
* | ||
* @author Thomas Krause <[email protected]> | ||
*/ | ||
public class IframeState extends JavaScriptComponentState | ||
{ | ||
private String source; | ||
private Integer lastScrollPos; | ||
|
||
public String getSource() | ||
{ | ||
return source; | ||
} | ||
|
||
public void setSource(String source) | ||
{ | ||
this.source = source; | ||
} | ||
|
||
public Integer getLastScrollPos() | ||
{ | ||
return lastScrollPos; | ||
} | ||
|
||
public void setLastScrollPos(Integer lastScrollPos) | ||
{ | ||
this.lastScrollPos = lastScrollPos; | ||
} | ||
|
||
|
||
|
||
} |
258 changes: 258 additions & 0 deletions
258
annis-gui/src/main/java/annis/gui/components/NavigateableSinglePage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
/* | ||
* Copyright 2014 Corpuslinguistic working group Humboldt University Berlin. | ||
* | ||
* 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 annis.gui.components; | ||
|
||
import com.vaadin.annotations.JavaScript; | ||
import com.vaadin.server.ConnectorResource; | ||
import com.vaadin.server.Resource; | ||
import com.vaadin.ui.AbstractJavaScriptComponent; | ||
import com.vaadin.ui.JavaScriptFunction; | ||
import com.vaadin.ui.MenuBar; | ||
import com.vaadin.ui.MenuBar.MenuItem; | ||
import com.vaadin.ui.VerticalLayout; | ||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.net.URI; | ||
import java.net.URL; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
import org.json.JSONArray; | ||
import org.json.JSONException; | ||
import org.jsoup.Jsoup; | ||
import org.jsoup.nodes.Document; | ||
import org.jsoup.nodes.Element; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* Embedds a single HTML page and adds navigation to it's headers (if they have | ||
* an id). | ||
* | ||
* This is e.g. usefull for documentation. | ||
* | ||
* @author Thomas Krause <[email protected]> | ||
*/ | ||
public class NavigateableSinglePage extends VerticalLayout | ||
{ | ||
|
||
private final static Logger log = LoggerFactory.getLogger( | ||
NavigateableSinglePage.class); | ||
|
||
private final IFrameComponent iframe = new IFrameComponent(); | ||
|
||
private MenuBar navigation; | ||
|
||
private final Map<String, MenuItem> menuItemRegistry = new HashMap<>(); | ||
|
||
private String lastSelectedID; | ||
|
||
private final static Pattern regexHeader = Pattern.compile("h([1-6])"); | ||
|
||
public NavigateableSinglePage(File localFile, URI externalURI) | ||
{ | ||
iframe.setSizeFull(); | ||
|
||
setSpacing(true); | ||
addComponent(iframe); | ||
|
||
setExpandRatio(iframe, 1.0f); | ||
|
||
setSource(localFile, externalURI); | ||
} | ||
|
||
private void onScroll(String headerID) | ||
{ | ||
selectChapterInNavigation(headerID); | ||
} | ||
|
||
private void setSource(File localFile, URI externalURI) | ||
{ | ||
iframe.getState().setSource(externalURI.toASCIIString()); | ||
if (navigation != null) | ||
{ | ||
removeComponent(navigation); | ||
} | ||
menuItemRegistry.clear(); | ||
navigation = createMenubarFromHTML(localFile, externalURI, menuItemRegistry); | ||
addComponent(navigation, 0); | ||
} | ||
|
||
private MenuBar createMenubarFromHTML(File localFile, URI externalURI, | ||
Map<String, MenuItem> idToMenuItem) | ||
{ | ||
|
||
MenuBar mbNavigation = new MenuBar(); | ||
mbNavigation.setStyleName("huge"); | ||
MenuItem navRoot = mbNavigation.addItem("Choose topic", null); | ||
navRoot.setStyleName("huge"); | ||
|
||
try(FileInputStream input = new FileInputStream(localFile)) | ||
{ | ||
Document doc = Jsoup.parse(input, "UTF-8", externalURI.toASCIIString()); | ||
|
||
ArrayList<MenuItem> itemPath = new ArrayList<>(); | ||
// find all headers that have an ID | ||
for (Element e : doc.getElementsByAttribute("id")) | ||
{ | ||
Matcher m = regexHeader.matcher(e.tagName()); | ||
if (m.matches()) | ||
{ | ||
int level = Integer.parseInt(m.group(1)) - 1; | ||
|
||
// decide wether to expand the path (one level deeper) or to truncate | ||
if (level == 0) | ||
{ | ||
itemPath.clear(); | ||
} | ||
else if (itemPath.size() >= level) | ||
{ | ||
// truncate | ||
itemPath = new ArrayList<>(itemPath.subList(0, level)); | ||
} | ||
|
||
if (itemPath.isEmpty() && level > 0) | ||
{ | ||
// fill the path with empty elements | ||
for (int i = 0; i < level; i++) | ||
{ | ||
itemPath.add(createItem(navRoot, itemPath, "<empty>", null)); | ||
} | ||
} | ||
MenuItem item = createItem(navRoot, itemPath, e.text(), e.id()); | ||
itemPath.add(item); | ||
idToMenuItem.put(e.id(), item); | ||
} | ||
} | ||
} | ||
catch (IOException ex) | ||
{ | ||
log.error("Could not parse iframe source", ex); | ||
} | ||
return mbNavigation; | ||
} | ||
|
||
private MenuItem createItem(MenuItem rootItem, List<MenuItem> path, | ||
String caption, String id) | ||
{ | ||
MenuItem parent; | ||
|
||
if (path.isEmpty()) | ||
{ | ||
parent = rootItem; | ||
} | ||
else | ||
{ | ||
parent = path.get(path.size() - 1); | ||
|
||
} | ||
MenuItem child = parent.addItem(caption, new IDSelectionCommand(id)); | ||
child.setStyleName("huge"); | ||
return child; | ||
} | ||
|
||
private void selectChapterInNavigation(String idToSelect) | ||
{ | ||
if (navigation != null && menuItemRegistry != null && idToSelect != null) | ||
{ | ||
MenuItem navRoot = navigation.getItems().get(0); | ||
MenuItem toSelect = menuItemRegistry.get(idToSelect); | ||
|
||
if (toSelect != null) | ||
{ | ||
navRoot.setText(toSelect.getText()); | ||
toSelect.setStyleName("huge-selected"); | ||
if(lastSelectedID != null) | ||
{ | ||
MenuItem lastSelectedItem = menuItemRegistry.get(lastSelectedID); | ||
if (lastSelectedItem != null && lastSelectedItem != toSelect) | ||
{ | ||
lastSelectedItem.setStyleName("huge"); | ||
} | ||
} | ||
lastSelectedID = idToSelect; | ||
} | ||
} | ||
} | ||
|
||
private class IDSelectionCommand implements MenuBar.Command | ||
{ | ||
|
||
private final String id; | ||
|
||
public IDSelectionCommand(String id) | ||
{ | ||
this.id = id; | ||
} | ||
|
||
@Override | ||
public void menuSelected(MenuItem selectedItem) | ||
{ | ||
if (id != null) | ||
{ | ||
iframe.scrollToElement(id); | ||
selectChapterInNavigation(id); | ||
} | ||
} | ||
|
||
} | ||
|
||
@JavaScript( | ||
{ | ||
"vaadin://jquery.js", "navigateablesinglepage.js" | ||
}) | ||
private class IFrameComponent extends AbstractJavaScriptComponent | ||
{ | ||
|
||
public IFrameComponent() | ||
{ | ||
addFunction("scrolled", new JavaScriptFunction() | ||
{ | ||
|
||
@Override | ||
public void call(JSONArray arguments) throws JSONException | ||
{ | ||
onScroll(arguments.getString(0)); | ||
getState().setLastScrollPos(arguments.getInt(1)); | ||
} | ||
}); | ||
} | ||
|
||
public void scrollToElement(String id) | ||
{ | ||
if(id != null) | ||
{ | ||
callFunction("scrollToElement", id); | ||
} | ||
} | ||
|
||
public void setSource(Resource res) | ||
{ | ||
setResource("content", res); | ||
} | ||
|
||
@Override | ||
public final IframeState getState() | ||
{ | ||
return (IframeState) super.getState(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.