From 7587c1a0419ee98b1cc750cec2ef366a9b85773e Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Sat, 15 Mar 2014 05:42:41 +0100 Subject: [PATCH] example: add ThemeStylerActivity --- vtm-android-example/AndroidManifest.xml | 11 +- .../res/layout/activity_map_styler.xml | 89 ++++++++ vtm-android-example/res/values/strings.xml | 4 + .../oscim/android/test/BaseMapActivity.java | 12 +- .../src/org/oscim/android/test/Samples.java | 1 + .../android/test/ThemeStylerActivity.java | 197 ++++++++++++++++++ 6 files changed, 307 insertions(+), 7 deletions(-) create mode 100644 vtm-android-example/res/layout/activity_map_styler.xml create mode 100644 vtm-android-example/src/org/oscim/android/test/ThemeStylerActivity.java diff --git a/vtm-android-example/AndroidManifest.xml b/vtm-android-example/AndroidManifest.xml index 0e0dcbc4..5634cf3d 100644 --- a/vtm-android-example/AndroidManifest.xml +++ b/vtm-android-example/AndroidManifest.xml @@ -16,7 +16,6 @@ android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" > - + + + diff --git a/vtm-android-example/res/layout/activity_map_styler.xml b/vtm-android-example/res/layout/activity_map_styler.xml new file mode 100644 index 00000000..1f622be2 --- /dev/null +++ b/vtm-android-example/res/layout/activity_map_styler.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vtm-android-example/res/values/strings.xml b/vtm-android-example/res/values/strings.xml index fdd1f739..3fd3af84 100644 --- a/vtm-android-example/res/values/strings.xml +++ b/vtm-android-example/res/values/strings.xml @@ -11,5 +11,9 @@ Cancel Error The selected file is invalid. + Line + Area + Outline + Controls \ No newline at end of file diff --git a/vtm-android-example/src/org/oscim/android/test/BaseMapActivity.java b/vtm-android-example/src/org/oscim/android/test/BaseMapActivity.java index b10ce96b..355db322 100644 --- a/vtm-android-example/src/org/oscim/android/test/BaseMapActivity.java +++ b/vtm-android-example/src/org/oscim/android/test/BaseMapActivity.java @@ -38,10 +38,20 @@ public class BaseMapActivity extends MapActivity { private TileCache mCache; + protected final int mContentView; + + public BaseMapActivity(int contentView) { + mContentView = contentView; + } + + public BaseMapActivity() { + this(R.layout.activity_map); + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_map); + setContentView(mContentView); mMapView = (MapView) findViewById(R.id.mapView); registerMapView(mMapView); diff --git a/vtm-android-example/src/org/oscim/android/test/Samples.java b/vtm-android-example/src/org/oscim/android/test/Samples.java index 6a4b511f..8dfa35ee 100644 --- a/vtm-android-example/src/org/oscim/android/test/Samples.java +++ b/vtm-android-example/src/org/oscim/android/test/Samples.java @@ -45,6 +45,7 @@ public class Samples extends Activity { linearLayout.addView(createButton(MapsforgeMapActivity.class)); linearLayout.addView(createButton(PathOverlayActivity.class)); linearLayout.addView(createButton(MarkerOverlayActivity.class)); + linearLayout.addView(createButton(ThemeStylerActivity.class)); } private Button createButton(final Class clazz) { diff --git a/vtm-android-example/src/org/oscim/android/test/ThemeStylerActivity.java b/vtm-android-example/src/org/oscim/android/test/ThemeStylerActivity.java new file mode 100644 index 00000000..6103b59a --- /dev/null +++ b/vtm-android-example/src/org/oscim/android/test/ThemeStylerActivity.java @@ -0,0 +1,197 @@ +package org.oscim.android.test; + +import static org.oscim.utils.ColorUtil.modHsv; +import static org.oscim.utils.ColorUtil.shiftHue; + +import org.oscim.layers.tile.vector.BuildingLayer; +import org.oscim.layers.tile.vector.VectorTileLayer; +import org.oscim.layers.tile.vector.labeling.LabelLayer; +import org.oscim.map.Layers; +import org.oscim.renderer.MapRenderer; +import org.oscim.theme.RenderTheme; +import org.oscim.theme.VtmThemes; +import org.oscim.theme.rule.Rule; +import org.oscim.theme.rule.Rule.RuleVisitor; +import org.oscim.theme.styles.AreaStyle; +import org.oscim.theme.styles.AreaStyle.AreaBuilder; +import org.oscim.theme.styles.LineStyle; +import org.oscim.theme.styles.LineStyle.LineBuilder; +import org.oscim.theme.styles.RenderStyle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import android.os.Bundle; +import android.view.View; +import android.widget.RadioButton; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.ToggleButton; + +public class ThemeStylerActivity extends BaseMapActivity implements OnSeekBarChangeListener { + final Logger log = LoggerFactory.getLogger(ThemeStylerActivity.class); + + public ThemeStylerActivity() { + super(R.layout.activity_map_styler); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ((SeekBar) findViewById(R.id.seekBarH)).setOnSeekBarChangeListener(this); + ((SeekBar) findViewById(R.id.seekBarS)).setOnSeekBarChangeListener(this); + ((SeekBar) findViewById(R.id.seekBarV)).setOnSeekBarChangeListener(this); + + Layers layers = mMap.layers(); + layers.add(new BuildingLayer(mMap, mBaseLayer)); + layers.add(new LabelLayer(mMap, mBaseLayer)); + + mMap.setTheme(VtmThemes.DEFAULT); + mMap.setMapPosition(53.08, 8.83, Math.pow(2, 10)); + } + + class ModStyleVisitor extends RuleVisitor { + private final LineBuilder lineBuilder = new LineBuilder(); + private final AreaBuilder areaBuilder = new AreaBuilder(); + + @Override + public void apply(Rule r) { + for (RenderStyle style : r.styles) { + + if (style instanceof LineStyle) { + LineStyle s = (LineStyle) style; + HSV c = lineColor; + if (lineColor.changed && s.outline) + continue; + + if (outlineColor.changed) { + if (!s.outline) + continue; + c = outlineColor; + } + + s.set(lineBuilder.set(s) + .color(modColor(s.color, c)) + .stippleColor(modColor(s.stippleColor, c)) + .build()); + continue; + } + + if (areaColor.changed && style instanceof AreaStyle) { + AreaStyle s = (AreaStyle) style; + + s.set(areaBuilder.set(s) + .color(modColor(s.color, areaColor)) + .blendColor(modColor(s.blendColor, areaColor)) + .build()); + + if (s.outline == null) + continue; + + s.outline.set(lineBuilder.set(s.outline) + .color(modColor(s.outline.color, areaColor)) + .stippleColor(modColor(s.outline.stippleColor, + areaColor)) + .build()); + } + } + super.apply(r); + } + } + + int modColor(int color, HSV hsv) { + return modHsv(shiftHue(color, hsv.hue), 1, hsv.sat, hsv.val, true); + } + + public static class HSV { + public double hue = 0; + public double sat = 1; + public double val = 1; + public boolean changed; + } + + HSV lineColor = new HSV(); + HSV outlineColor = new HSV(); + HSV areaColor = new HSV(); + + ModStyleVisitor mStyleVisitor = new ModStyleVisitor(); + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (!fromUser) + return; + int id = seekBar.getId(); + + boolean modLine = ((RadioButton) findViewById(R.id.checkBoxLine)).isChecked(); + boolean modArea = ((RadioButton) findViewById(R.id.checkBoxArea)).isChecked(); + + HSV c; + if (modArea) + c = areaColor; + else if (modLine) + c = lineColor; + else + c = outlineColor; + + if (id == R.id.seekBarS) + c.sat = progress / 50f; + else if (id == R.id.seekBarV) + c.val = progress / 50f; + else if (id == R.id.seekBarH) + c.hue = progress / 100f; + + log.debug((modArea ? "area" : "line") + + " h:" + c.hue + + " s:" + c.sat + + " v:" + c.val); + + VectorTileLayer l = (VectorTileLayer) mMap.layers().get(1); + RenderTheme t = (RenderTheme) l.getTheme(); + + c.changed = true; + t.traverseRules(mStyleVisitor); + t.updateStyles(); + c.changed = false; + + if (modArea) + MapRenderer.setBackgroundColor(modColor(t.getMapBackground(), c)); + + mMap.render(); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + + public void onToggleControls(View view) { + findViewById(R.id.controls).setVisibility(((ToggleButton) view).isChecked() ? + View.VISIBLE : View.GONE); + } + + public void onRadioButtonClicked(View view) { + boolean checked = ((RadioButton) view).isChecked(); + if (!checked) + return; + + HSV c = null; + switch (view.getId()) { + case R.id.checkBoxArea: + c = areaColor; + break; + case R.id.checkBoxLine: + c = lineColor; + break; + case R.id.checkBoxOutline: + c = outlineColor; + break; + } + if (c == null) + return; + ((SeekBar) findViewById(R.id.seekBarS)).setProgress((int) (c.sat * 50)); + ((SeekBar) findViewById(R.id.seekBarV)).setProgress((int) (c.val * 50)); + ((SeekBar) findViewById(R.id.seekBarH)).setProgress((int) (c.hue * 100)); + } +}