summaryrefslogtreecommitdiff
path: root/platform/macos
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2016-08-21 13:01:09 -0700
committerMinh Nguyễn <mxn@1ec5.org>2016-11-28 15:45:43 -0800
commit992726ab492bad5bddd49a5a5c3e57764f1998b9 (patch)
treed2ff202943ca57b0f7ca0307e7feb73c7091b33c /platform/macos
parent03a2dbe3615cd525d091e49f640f960fa2b28a81 (diff)
downloadqtlocation-mapboxgl-992726ab492bad5bddd49a5a5c3e57764f1998b9.tar.gz
[macos] Added Layers sidebar
Added a sidebar to the main document window in macosapp that lists the layers in the current style and updates whenever the style changes or a layer is added or removed programmatically. Display an icon beside each layer in the sidebar that indicates the kind of layer. Double-click a layer or layers to toggle their visibility, which is an undoable action. Added a menu item and toolbar button to toggle the Layers sidebar. Added a context menu for toggling visibility of and deleting layers selected in the Layers sidebar. Checked in the original SVGs for layer icons.
Diffstat (limited to 'platform/macos')
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/Contents.json6
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/background.imageset/Contents.json15
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/background.imageset/background.pdf69
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/circle.imageset/Contents.json15
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/circle.imageset/circle.pdf70
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/fill.imageset/Contents.json15
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/fill.imageset/fill.pdfbin0 -> 1046 bytes
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/symbol.imageset/Contents.json15
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/symbol.imageset/symbol.pdf71
-rw-r--r--platform/macos/app/Base.lproj/MainMenu.xib5
-rw-r--r--platform/macos/app/Base.lproj/MapDocument.xib185
-rw-r--r--platform/macos/app/MapDocument.m150
-rw-r--r--platform/macos/app/StyleLayerIconTransformer.h5
-rw-r--r--platform/macos/app/StyleLayerIconTransformer.m38
-rw-r--r--platform/macos/app/resources/background.svg90
-rw-r--r--platform/macos/app/resources/circle.svg67
-rw-r--r--platform/macos/app/resources/fill.svg68
-rw-r--r--platform/macos/app/resources/symbol.svg66
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj6
19 files changed, 940 insertions, 16 deletions
diff --git a/platform/macos/app/Assets.xcassets/Layers/Contents.json b/platform/macos/app/Assets.xcassets/Layers/Contents.json
new file mode 100644
index 0000000000..da4a164c91
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Layers/background.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Layers/background.imageset/Contents.json
new file mode 100644
index 0000000000..3d2c878879
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/background.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "background.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Layers/background.imageset/background.pdf b/platform/macos/app/Assets.xcassets/Layers/background.imageset/background.pdf
new file mode 100644
index 0000000000..95a50c1446
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/background.imageset/background.pdf
@@ -0,0 +1,69 @@
+%PDF-1.5
+%
+3 0 obj
+<< /Length 4 0 R
+ /Filter /FlateDecode
+>>
+stream
+x}Mj@ u
+] *I Hf1x ܋E?Oն ChgՓT>R2}̃7e7=y!^Epp$aC QeQavJ$6r\+6"uTwtȂ܄Cpoz>(@ \Q@Xx^o6f58KP::ۨv:DmEQu/z\';*U 2.޻2Up!ν5D>!PVQNvkhK:WEt1^9du.!Y c:Ox>1`,iDi(1^mc3ʸ`#(vKWt/Ѝ"5I7ag+vܧX1sփ!?8
+endstream
+endobj
+4 0 obj
+ 424
+endobj
+2 0 obj
+<<
+ /ExtGState <<
+ /a0 << /CA 1 /ca 1 >>
+ >>
+>>
+endobj
+5 0 obj
+<< /Type /Page
+ /Parent 1 0 R
+ /MediaBox [ 0 0 12.8 12.8 ]
+ /Contents 3 0 R
+ /Group <<
+ /Type /Group
+ /S /Transparency
+ /I true
+ /CS /DeviceRGB
+ >>
+ /Resources 2 0 R
+>>
+endobj
+1 0 obj
+<< /Type /Pages
+ /Kids [ 5 0 R ]
+ /Count 1
+>>
+endobj
+6 0 obj
+<< /Creator (cairo 1.14.0 (http://cairographics.org))
+ /Producer (cairo 1.14.0 (http://cairographics.org))
+>>
+endobj
+7 0 obj
+<< /Type /Catalog
+ /Pages 1 0 R
+>>
+endobj
+xref
+0 8
+0000000000 65535 f
+0000000826 00000 n
+0000000538 00000 n
+0000000015 00000 n
+0000000516 00000 n
+0000000610 00000 n
+0000000891 00000 n
+0000001018 00000 n
+trailer
+<< /Size 8
+ /Root 7 0 R
+ /Info 6 0 R
+>>
+startxref
+1070
+%%EOF
diff --git a/platform/macos/app/Assets.xcassets/Layers/circle.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Layers/circle.imageset/Contents.json
new file mode 100644
index 0000000000..c924214fd9
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/circle.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "circle.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Layers/circle.imageset/circle.pdf b/platform/macos/app/Assets.xcassets/Layers/circle.imageset/circle.pdf
new file mode 100644
index 0000000000..fde79a19bd
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/circle.imageset/circle.pdf
@@ -0,0 +1,70 @@
+%PDF-1.5
+%
+3 0 obj
+<< /Length 4 0 R
+ /Filter /FlateDecode
+>>
+stream
+x]M
+1 9Ż1?''aRAf1 X)GK ANv_4Nܩ š% 3Z
+cr'QJ2Wp{t\dImW 44J
+endstream
+endobj
+4 0 obj
+ 139
+endobj
+2 0 obj
+<<
+ /ExtGState <<
+ /a0 << /CA 1 /ca 1 >>
+ >>
+>>
+endobj
+5 0 obj
+<< /Type /Page
+ /Parent 1 0 R
+ /MediaBox [ 0 0 12.8 12.8 ]
+ /Contents 3 0 R
+ /Group <<
+ /Type /Group
+ /S /Transparency
+ /I true
+ /CS /DeviceRGB
+ >>
+ /Resources 2 0 R
+>>
+endobj
+1 0 obj
+<< /Type /Pages
+ /Kids [ 5 0 R ]
+ /Count 1
+>>
+endobj
+6 0 obj
+<< /Creator (cairo 1.14.0 (http://cairographics.org))
+ /Producer (cairo 1.14.0 (http://cairographics.org))
+>>
+endobj
+7 0 obj
+<< /Type /Catalog
+ /Pages 1 0 R
+>>
+endobj
+xref
+0 8
+0000000000 65535 f
+0000000541 00000 n
+0000000253 00000 n
+0000000015 00000 n
+0000000231 00000 n
+0000000325 00000 n
+0000000606 00000 n
+0000000733 00000 n
+trailer
+<< /Size 8
+ /Root 7 0 R
+ /Info 6 0 R
+>>
+startxref
+785
+%%EOF
diff --git a/platform/macos/app/Assets.xcassets/Layers/fill.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Layers/fill.imageset/Contents.json
new file mode 100644
index 0000000000..ea68330e70
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/fill.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "fill.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Layers/fill.imageset/fill.pdf b/platform/macos/app/Assets.xcassets/Layers/fill.imageset/fill.pdf
new file mode 100644
index 0000000000..ca7e4cc505
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/fill.imageset/fill.pdf
Binary files differ
diff --git a/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/Contents.json
new file mode 100644
index 0000000000..ad4293958f
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "symbol.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/symbol.pdf b/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/symbol.pdf
new file mode 100644
index 0000000000..ce4aaa198e
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/symbol.pdf
@@ -0,0 +1,71 @@
+%PDF-1.5
+%
+3 0 obj
+<< /Length 4 0 R
+ /Filter /FlateDecode
+>>
+stream
+x]A
+@ E9ſqIgR\EqqQ !'
+ua{ HXRLQ&~'/p#!ʎ26a0scR_CYr씪KFʖ9O׋.pN- yV
+yOh4
+endstream
+endobj
+4 0 obj
+ 152
+endobj
+2 0 obj
+<<
+ /ExtGState <<
+ /a0 << /CA 1 /ca 1 >>
+ >>
+>>
+endobj
+5 0 obj
+<< /Type /Page
+ /Parent 1 0 R
+ /MediaBox [ 0 0 12.8 12.8 ]
+ /Contents 3 0 R
+ /Group <<
+ /Type /Group
+ /S /Transparency
+ /I true
+ /CS /DeviceRGB
+ >>
+ /Resources 2 0 R
+>>
+endobj
+1 0 obj
+<< /Type /Pages
+ /Kids [ 5 0 R ]
+ /Count 1
+>>
+endobj
+6 0 obj
+<< /Creator (cairo 1.14.0 (http://cairographics.org))
+ /Producer (cairo 1.14.0 (http://cairographics.org))
+>>
+endobj
+7 0 obj
+<< /Type /Catalog
+ /Pages 1 0 R
+>>
+endobj
+xref
+0 8
+0000000000 65535 f
+0000000554 00000 n
+0000000266 00000 n
+0000000015 00000 n
+0000000244 00000 n
+0000000338 00000 n
+0000000619 00000 n
+0000000746 00000 n
+trailer
+<< /Size 8
+ /Root 7 0 R
+ /Info 6 0 R
+>>
+startxref
+798
+%%EOF
diff --git a/platform/macos/app/Base.lproj/MainMenu.xib b/platform/macos/app/Base.lproj/MainMenu.xib
index 7dd4d08430..4efb8d4c46 100644
--- a/platform/macos/app/Base.lproj/MainMenu.xib
+++ b/platform/macos/app/Base.lproj/MainMenu.xib
@@ -429,6 +429,11 @@
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
</connections>
</menuItem>
+ <menuItem title="Show Layers" keyEquivalent="L" id="qtg-l9-BH3">
+ <connections>
+ <action selector="toggleLayers:" target="-1" id="YdA-Mr-MHi"/>
+ </connections>
+ </menuItem>
</items>
</menu>
</menuItem>
diff --git a/platform/macos/app/Base.lproj/MapDocument.xib b/platform/macos/app/Base.lproj/MapDocument.xib
index 4e58490e68..9af40d461d 100644
--- a/platform/macos/app/Base.lproj/MapDocument.xib
+++ b/platform/macos/app/Base.lproj/MapDocument.xib
@@ -1,40 +1,160 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11191" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="15G1004" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
- <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11191"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="MapDocument">
<connections>
<outlet property="mapView" destination="q4d-kF-8Hi" id="7hI-dS-A5R"/>
<outlet property="mapViewContextMenu" destination="XbX-6a-Mgy" id="YD0-1r-5N2"/>
+ <outlet property="splitView" destination="IPR-fm-vk8" id="9xt-ar-uad"/>
+ <outlet property="styleLayersArrayController" destination="GXW-3J-Gff" id="Ygs-7o-juz"/>
+ <outlet property="styleLayersTableView" destination="Mm4-6F-qEb" id="TB5-ha-JJE"/>
<outlet property="window" destination="cSv-fg-MAQ" id="TBu-Mu-79N"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+ <objectController objectClassName="MGLMapView" id="jxx-uM-ZTC" userLabel="Map View Object Controller">
+ <declaredKeys>
+ <string>style</string>
+ </declaredKeys>
+ <connections>
+ <outlet property="content" destination="q4d-kF-8Hi" id="Zpe-0y-eG3"/>
+ </connections>
+ </objectController>
+ <objectController objectClassName="MGLStyle" id="Xji-k6-iQ4" userLabel="Style Object Controller">
+ <declaredKeys>
+ <string>layers</string>
+ </declaredKeys>
+ <connections>
+ <binding destination="jxx-uM-ZTC" name="contentObject" keyPath="selection.style" id="60N-aU-tgJ"/>
+ </connections>
+ </objectController>
+ <arrayController objectClassName="MGLStyleLayer" avoidsEmptySelection="NO" id="GXW-3J-Gff" userLabel="Style Layers Array Controller">
+ <declaredKeys>
+ <string>identifier</string>
+ <string>visible</string>
+ </declaredKeys>
+ <connections>
+ <binding destination="Xji-k6-iQ4" name="contentArray" keyPath="selection.layers" id="X25-Nb-Brf"/>
+ </connections>
+ </arrayController>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" frameAutosaveName="MBXMapWindow" animationBehavior="default" id="cSv-fg-MAQ">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
- <rect key="contentRect" x="388" y="211" width="512" height="480"/>
+ <rect key="contentRect" x="388" y="211" width="642" height="480"/>
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
<view key="contentView" id="TuG-C5-zLS">
- <rect key="frame" x="0.0" y="0.0" width="512" height="480"/>
+ <rect key="frame" x="0.0" y="0.0" width="642" height="480"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
- <customView translatesAutoresizingMaskIntoConstraints="NO" id="q4d-kF-8Hi" customClass="MGLMapView">
- <rect key="frame" x="0.0" y="0.0" width="512" height="480"/>
+ <splitView autosaveName="MBXLayersSplitView" dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="IPR-fm-vk8">
+ <rect key="frame" x="0.0" y="0.0" width="642" height="480"/>
+ <subviews>
+ <scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="sMc-vT-RwH">
+ <rect key="frame" x="0.0" y="0.0" width="163" height="480"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <clipView key="contentView" id="bSc-hK-bzQ">
+ <rect key="frame" x="0.0" y="0.0" width="163" height="480"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" id="Mm4-6F-qEb">
+ <rect key="frame" x="0.0" y="0.0" width="163" height="480"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <size key="intercellSpacing" width="3" height="2"/>
+ <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+ <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
+ <tableColumns>
+ <tableColumn editable="NO" width="16" minWidth="16" maxWidth="1000" id="P3U-a3-c8q">
+ <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
+ <font key="font" metaFont="smallSystem"/>
+ <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
+ </tableHeaderCell>
+ <imageCell key="dataCell" lineBreakMode="truncatingTail" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="symbol" id="JWq-c8-aB1"/>
+ <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
+ <connections>
+ <binding destination="GXW-3J-Gff" name="value" keyPath="arrangedObjects" id="ST5-mo-Mkt">
+ <dictionary key="options">
+ <bool key="NSConditionallySetsEnabled" value="NO"/>
+ <string key="NSValueTransformerName">StyleLayerIconTransformer</string>
+ </dictionary>
+ </binding>
+ </connections>
+ </tableColumn>
+ <tableColumn editable="NO" width="141" minWidth="40" maxWidth="1000" id="BwD-ww-7uw">
+ <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
+ <font key="font" metaFont="smallSystem"/>
+ <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
+ </tableHeaderCell>
+ <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="6wl-F2-yK2">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
+ <connections>
+ <binding destination="GXW-3J-Gff" name="value" keyPath="arrangedObjects.identifier" id="vQC-tc-CMF">
+ <dictionary key="options">
+ <bool key="NSConditionallySetsEditable" value="YES"/>
+ </dictionary>
+ </binding>
+ <binding destination="GXW-3J-Gff" name="fontItalic" keyPath="arrangedObjects.visible" id="6Wu-cz-WSI">
+ <dictionary key="options">
+ <string key="NSValueTransformerName">NSNegateBoolean</string>
+ </dictionary>
+ </binding>
+ </connections>
+ </tableColumn>
+ </tableColumns>
+ <connections>
+ <action trigger="doubleAction" selector="toggleStyleLayers:" target="-1" id="Q1v-2T-sIC"/>
+ <outlet property="menu" destination="OHX-Pa-tDw" id="wnL-Ux-WaH"/>
+ </connections>
+ </tableView>
+ </subviews>
+ </clipView>
+ <constraints>
+ <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="185" id="VQs-2Z-hmP"/>
+ </constraints>
+ <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="NDx-rn-TLj">
+ <rect key="frame" x="0.0" y="464" width="184.5" height="16"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </scroller>
+ <scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="0vt-rI-sHB">
+ <rect key="frame" x="147" y="480" width="16" height="0.0"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </scroller>
+ </scrollView>
+ <customView id="q4d-kF-8Hi" customClass="MGLMapView">
+ <rect key="frame" x="164" y="0.0" width="478" height="480"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <constraints>
+ <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="200" id="kg3-4h-7Hl"/>
+ </constraints>
+ <connections>
+ <outlet property="delegate" destination="-2" id="dh2-0H-jFZ"/>
+ <outlet property="menu" destination="XbX-6a-Mgy" id="dSu-HR-Kq2"/>
+ </connections>
+ </customView>
+ </subviews>
+ <holdingPriorities>
+ <real value="250"/>
+ <real value="250"/>
+ </holdingPriorities>
<connections>
- <outlet property="delegate" destination="-2" id="dh2-0H-jFZ"/>
- <outlet property="menu" destination="XbX-6a-Mgy" id="dSu-HR-Kq2"/>
+ <outlet property="delegate" destination="-2" id="dbC-MC-CAy"/>
</connections>
- </customView>
+ </splitView>
</subviews>
<constraints>
- <constraint firstAttribute="bottom" secondItem="q4d-kF-8Hi" secondAttribute="bottom" id="L2t-Be-qWL"/>
- <constraint firstItem="q4d-kF-8Hi" firstAttribute="top" secondItem="TuG-C5-zLS" secondAttribute="top" id="T8A-o3-Bhq"/>
- <constraint firstItem="q4d-kF-8Hi" firstAttribute="leading" secondItem="TuG-C5-zLS" secondAttribute="leading" id="fGH-YW-Qd3"/>
- <constraint firstAttribute="trailing" secondItem="q4d-kF-8Hi" secondAttribute="trailing" id="yfG-iG-K4C"/>
+ <constraint firstAttribute="trailing" secondItem="IPR-fm-vk8" secondAttribute="trailing" id="ABk-5R-Uzg"/>
+ <constraint firstAttribute="bottom" secondItem="IPR-fm-vk8" secondAttribute="bottom" id="CHa-BK-6ld"/>
+ <constraint firstItem="IPR-fm-vk8" firstAttribute="leading" secondItem="TuG-C5-zLS" secondAttribute="leading" id="hcR-y2-x3l"/>
+ <constraint firstItem="IPR-fm-vk8" firstAttribute="top" secondItem="TuG-C5-zLS" secondAttribute="top" id="u78-BU-s5g"/>
</constraints>
</view>
<toolbar key="toolbar" implicitIdentifier="A3AC6577-4712-4628-813D-113498171A84" allowsUserCustomization="NO" displayMode="iconOnly" sizeMode="regular" id="DTc-AP-Bah">
@@ -89,8 +209,25 @@
<action selector="showStyle:" target="-1" id="pBn-SO-HIX"/>
</connections>
</toolbarItem>
+ <toolbarItem implicitItemIdentifier="ACA1D8BE-A108-4BF9-92DC-AE7AA7342CF9" label="Layers" paletteLabel="Show Layers" image="NSListViewTemplate" id="THR-Dm-mn8" customClass="ValidatedToolbarItem">
+ <nil key="toolTip"/>
+ <size key="minSize" width="47" height="32"/>
+ <size key="maxSize" width="48" height="32"/>
+ <button key="view" verticalHuggingPriority="750" id="C3e-Oy-STT">
+ <rect key="frame" x="14" y="14" width="47" height="32"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSListViewTemplate" imagePosition="only" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="2Gf-wm-QuI">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ </button>
+ <connections>
+ <action selector="toggleLayers:" target="-1" id="NHT-rn-BuG"/>
+ </connections>
+ </toolbarItem>
</allowedToolbarItems>
<defaultToolbarItems>
+ <toolbarItem reference="THR-Dm-mn8"/>
<toolbarItem reference="XJT-Ho-tuZ"/>
<toolbarItem reference="z4l-5x-MzK"/>
<toolbarItem reference="u23-0z-Otl"/>
@@ -135,8 +272,30 @@
</connections>
<point key="canvasLocation" x="820" y="254.5"/>
</menu>
+ <menu title="Layer" id="OHX-Pa-tDw" userLabel="Layers Context Menu">
+ <items>
+ <menuItem title="Show" id="KWq-LM-Qqo">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleStyleLayers:" target="-1" id="kXn-ug-tWC"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="uWQ-uj-mZn"/>
+ <menuItem title="Delete" id="Myg-EZ-Pnq">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="deleteStyleLayers:" target="-1" id="cE5-ZP-BDC"/>
+ </connections>
+ </menuItem>
+ </items>
+ <connections>
+ <outlet property="delegate" destination="-2" id="yvb-NB-VGl"/>
+ </connections>
+ </menu>
</objects>
<resources>
+ <image name="NSListViewTemplate" width="14" height="10"/>
<image name="NSShareTemplate" width="11" height="16"/>
+ <image name="symbol" width="13" height="13"/>
</resources>
</document>
diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m
index f9477206aa..e312eccca2 100644
--- a/platform/macos/app/MapDocument.m
+++ b/platform/macos/app/MapDocument.m
@@ -46,9 +46,12 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
return flattenedShapes;
}
-@interface MapDocument () <NSWindowDelegate, NSSharingServicePickerDelegate, NSMenuDelegate, MGLMapViewDelegate>
+@interface MapDocument () <NSWindowDelegate, NSSharingServicePickerDelegate, NSMenuDelegate, NSSplitViewDelegate, MGLMapViewDelegate>
+@property (weak) IBOutlet NSArrayController *styleLayersArrayController;
+@property (weak) IBOutlet NSTableView *styleLayersTableView;
@property (weak) IBOutlet NSMenu *mapViewContextMenu;
+@property (weak) IBOutlet NSSplitView *splitView;
@end
@@ -98,6 +101,8 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
NSPressGestureRecognizer *pressGestureRecognizer = [[NSPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlePressGesture:)];
[self.mapView addGestureRecognizer:pressGestureRecognizer];
+ [self.splitView setPosition:0 ofDividerAtIndex:0];
+
[self applyPendingState];
}
@@ -174,6 +179,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
NSAssert(NO, @"Cannot set style from control with tag %li", (long)tag);
break;
}
+ [self.undoManager removeAllActionsWithTarget:self];
self.mapView.styleURL = styleURL;
[self.window.toolbar validateVisibleItems];
}
@@ -195,6 +201,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
[alert addButtonWithTitle:@"Apply"];
[alert addButtonWithTitle:@"Cancel"];
if ([alert runModal] == NSAlertFirstButtonReturn) {
+ [self.undoManager removeAllActionsWithTarget:self];
self.mapView.styleURL = [NSURL URLWithString:textField.stringValue];
[[NSUserDefaults standardUserDefaults] setURL:self.mapView.styleURL forKey:@"MBXCustomStyleURL"];
[self.window.toolbar validateVisibleItems];
@@ -214,9 +221,110 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
}
- (IBAction)reload:(id)sender {
+ [self.undoManager removeAllActionsWithTarget:self];
[self.mapView reloadStyle:sender];
}
+/**
+ Show or hide the Layers sidebar.
+ */
+- (IBAction)toggleLayers:(id)sender {
+ BOOL isShown = ![self.splitView isSubviewCollapsed:self.splitView.arrangedSubviews.firstObject];
+ [NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) {
+ context.allowsImplicitAnimation = YES;
+ [self.splitView setPosition:isShown ? 0 : 100 ofDividerAtIndex:0];
+ [self.window.toolbar validateVisibleItems];
+ } completionHandler:nil];
+}
+
+/**
+ Show or hide the selected layers.
+ */
+- (IBAction)toggleStyleLayers:(id)sender {
+ NSInteger clickedRow = self.styleLayersTableView.clickedRow;
+ NSIndexSet *indices = self.styleLayersTableView.selectedRowIndexes;
+ if (clickedRow >= 0 && ![indices containsIndex:clickedRow]) {
+ indices = [NSIndexSet indexSetWithIndex:clickedRow];
+ }
+ [self toggleStyleLayersAtArrangedObjectIndexes:indices];
+}
+
+- (void)toggleStyleLayersAtArrangedObjectIndexes:(NSIndexSet *)indices {
+ NS_ARRAY_OF(MGLStyleLayer *) *layers = [self.mapView.style.layers objectsAtIndexes:indices];
+ BOOL isVisible = layers.firstObject.visible;
+ [self.undoManager registerUndoWithTarget:self handler:^(MapDocument * _Nonnull target) {
+ [target toggleStyleLayersAtArrangedObjectIndexes:indices];
+ }];
+
+ if (!self.undoManager.undoing) {
+ NSString *actionName;
+ if (indices.count == 1) {
+ actionName = [NSString stringWithFormat:@"%@ Layer “%@”", isVisible ? @"Hide" : @"Show", layers.firstObject.identifier];
+ } else {
+ actionName = [NSString stringWithFormat:@"%@ %@ Layers", isVisible ? @"Hide" : @"Show",
+ [NSNumberFormatter localizedStringFromNumber:@(indices.count)
+ numberStyle:NSNumberFormatterDecimalStyle]];
+ }
+ [self.undoManager setActionIsDiscardable:YES];
+ [self.undoManager setActionName:actionName];
+ }
+
+ for (MGLStyleLayer *layer in layers) {
+ layer.visible = !isVisible;
+ }
+
+ NSIndexSet *columnIndices = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)];
+ [self.styleLayersTableView reloadDataForRowIndexes:indices columnIndexes:columnIndices];
+}
+
+- (IBAction)deleteStyleLayers:(id)sender {
+ NSInteger clickedRow = self.styleLayersTableView.clickedRow;
+ NSIndexSet *indices = self.styleLayersTableView.selectedRowIndexes;
+ if (clickedRow >= 0 && ![indices containsIndex:clickedRow]) {
+ indices = [NSIndexSet indexSetWithIndex:clickedRow];
+ }
+ [self deleteStyleLayersAtArrangedObjectIndexes:indices];
+}
+
+- (void)insertStyleLayers:(NS_ARRAY_OF(MGLStyleLayer *) *)layers atArrangedObjectIndexes:(NSIndexSet *)indices {
+ [self.undoManager registerUndoWithTarget:self handler:^(id _Nonnull target) {
+ [self deleteStyleLayersAtArrangedObjectIndexes:indices];
+ }];
+
+ if (!self.undoManager.undoing) {
+ NSString *actionName;
+ if (indices.count == 1) {
+ actionName = [NSString stringWithFormat:@"Add Layer “%@”", layers.firstObject.identifier];
+ } else {
+ actionName = [NSString stringWithFormat:@"Add %@ Layers",
+ [NSNumberFormatter localizedStringFromNumber:@(indices.count) numberStyle:NSNumberFormatterDecimalStyle]];
+ }
+ [self.undoManager setActionName:actionName];
+ }
+
+ [self.styleLayersArrayController insertObjects:layers atArrangedObjectIndexes:indices];
+}
+
+- (void)deleteStyleLayersAtArrangedObjectIndexes:(NSIndexSet *)indices {
+ NS_ARRAY_OF(MGLStyleLayer *) *layers = [self.mapView.style.layers objectsAtIndexes:indices];
+ [self.undoManager registerUndoWithTarget:self handler:^(id _Nonnull target) {
+ [self insertStyleLayers:layers atArrangedObjectIndexes:indices];
+ }];
+
+ if (!self.undoManager.undoing) {
+ NSString *actionName;
+ if (indices.count == 1) {
+ actionName = [NSString stringWithFormat:@"Delete Layer “%@”", layers.firstObject.identifier];
+ } else {
+ actionName = [NSString stringWithFormat:@"Delete %@ Layers",
+ [NSNumberFormatter localizedStringFromNumber:@(indices.count) numberStyle:NSNumberFormatterDecimalStyle]];
+ }
+ [self.undoManager setActionName:actionName];
+ }
+
+ [self.styleLayersArrayController removeObjectsAtArrangedObjectIndexes:indices];
+}
+
- (void)applyPendingState {
if (_inheritedStyleURL) {
self.mapView.styleURL = _inheritedStyleURL;
@@ -607,6 +715,27 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
if (menuItem.action == @selector(reload:)) {
return YES;
}
+ if (menuItem.action == @selector(toggleLayers:)) {
+ BOOL isShown = ![self.splitView isSubviewCollapsed:self.splitView.arrangedSubviews.firstObject];
+ menuItem.title = isShown ? @"Hide Layers" : @"Show Layers";
+ return YES;
+ }
+ if (menuItem.action == @selector(toggleStyleLayers:)) {
+ NSInteger row = self.styleLayersTableView.clickedRow;
+ if (row == -1) {
+ row = self.styleLayersTableView.selectedRow;
+ }
+ if (row == -1) {
+ menuItem.title = @"Show";
+ } else {
+ BOOL isVisible = self.mapView.style.layers[row].visible;
+ menuItem.title = isVisible ? @"Hide" : @"Show";
+ }
+ return row != -1;
+ }
+ if (menuItem.action == @selector(deleteStyleLayers:)) {
+ return self.styleLayersTableView.clickedRow >= 0 || self.styleLayersTableView.selectedRow >= 0;
+ }
if (menuItem.action == @selector(manipulateStyle:)) {
return YES;
}
@@ -722,7 +851,8 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
return NO;
}
- if (toolbarItem.action == @selector(showShareMenu:)) {
+ SEL action = toolbarItem.action;
+ if (action == @selector(showShareMenu:)) {
[(NSButton *)toolbarItem.view sendActionOn:NSLeftMouseDownMask];
if (![MGLAccountManager accessToken]) {
return NO;
@@ -731,7 +861,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
return ([styleURL.scheme isEqualToString:@"mapbox"]
&& [styleURL.pathComponents.firstObject isEqualToString:@"styles"]);
}
- if (toolbarItem.action == @selector(showStyle:)) {
+ if (action == @selector(showStyle:)) {
NSPopUpButton *popUpButton = (NSPopUpButton *)toolbarItem.view;
NSUInteger index = self.indexOfStyleInToolbarItem;
if (index == NSNotFound) {
@@ -740,6 +870,10 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
}
[popUpButton selectItemAtIndex:index];
}
+ if (action == @selector(toggleLayers:)) {
+ BOOL isShown = ![self.splitView isSubviewCollapsed:self.splitView.arrangedSubviews.firstObject];
+ [(NSButton *)toolbarItem.view setState:isShown ? NSOnState : NSOffState];
+ }
return NO;
}
@@ -773,6 +907,16 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
}
}
+#pragma mark NSSplitViewDelegate methods
+
+- (BOOL)splitView:(NSSplitView *)splitView canCollapseSubview:(NSView *)subview {
+ return subview != self.mapView;
+}
+
+- (BOOL)splitView:(NSSplitView *)splitView shouldCollapseSubview:(NSView *)subview forDoubleClickOnDividerAtIndex:(NSInteger)dividerIndex {
+ return YES;
+}
+
#pragma mark MGLMapViewDelegate methods
- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id <MGLAnnotation>)annotation {
diff --git a/platform/macos/app/StyleLayerIconTransformer.h b/platform/macos/app/StyleLayerIconTransformer.h
new file mode 100644
index 0000000000..1af1d512d6
--- /dev/null
+++ b/platform/macos/app/StyleLayerIconTransformer.h
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+
+@interface StyleLayerIconTransformer : NSValueTransformer
+
+@end
diff --git a/platform/macos/app/StyleLayerIconTransformer.m b/platform/macos/app/StyleLayerIconTransformer.m
new file mode 100644
index 0000000000..93f59abb3e
--- /dev/null
+++ b/platform/macos/app/StyleLayerIconTransformer.m
@@ -0,0 +1,38 @@
+#import "StyleLayerIconTransformer.h"
+
+#import <Mapbox/Mapbox.h>
+
+@implementation StyleLayerIconTransformer
+
++ (Class)transformedValueClass {
+ return [NSString class];
+}
+
++ (BOOL)allowsReverseTransformation {
+ return NO;
+}
+
+- (id)transformedValue:(MGLStyleLayer *)layer {
+ if ([layer isKindOfClass:[MGLBackgroundStyleLayer class]]) {
+ return [NSImage imageNamed:@"background"];
+ }
+ if ([layer isKindOfClass:[MGLCircleStyleLayer class]]) {
+ return [NSImage imageNamed:@"circle"];
+ }
+ if ([layer isKindOfClass:[MGLFillStyleLayer class]]) {
+ return [NSImage imageNamed:@"fill"];
+ }
+ if ([layer isKindOfClass:[MGLLineStyleLayer class]]) {
+ return [NSImage imageNamed:@"NSListViewTemplate"];
+ }
+ if ([layer isKindOfClass:[MGLRasterStyleLayer class]]) {
+ return [[NSWorkspace sharedWorkspace] iconForFileType:@"jpg"];
+ }
+ if ([layer isKindOfClass:[MGLSymbolStyleLayer class]]) {
+ return [NSImage imageNamed:@"symbol"];
+ }
+
+ return nil;
+}
+
+@end
diff --git a/platform/macos/app/resources/background.svg b/platform/macos/app/resources/background.svg
new file mode 100644
index 0000000000..39451e8b13
--- /dev/null
+++ b/platform/macos/app/resources/background.svg
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ id="svg4148"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="background.svg"
+ inkscape:export-filename="/Users/mxn/Desktop/symbol.png"
+ inkscape:export-xdpi="90.000244"
+ inkscape:export-ydpi="90.000244">
+ <defs
+ id="defs4150">
+ <inkscape:path-effect
+ effect="spiro"
+ id="path-effect4877"
+ is_visible="true" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="10.48171"
+ inkscape:cx="8.5046012"
+ inkscape:cy="7.2814248"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:window-width="1280"
+ inkscape:window-height="751"
+ inkscape:window-x="0"
+ inkscape:window-y="1"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata4153">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 2.8621284,1037.3477 c 2.5635185,5.7342 4.4524268,0.068 4.4524268,0.068 l 0.067461,-5e-4 c 2.4960576,4.9921 4.1825828,-0.1349 4.1825828,-0.1349 l 0.02385,0 c 2.765902,5.5993 4.091271,0 4.091271,0 l 0.02385,0 c 3.170668,5.9366 4.293654,0 4.293654,0"
+ id="path4893"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -4.1486618,1041.2371 c 2.5635185,5.7342 4.45242682,0.068 4.45242682,0.068 l 0.067461,-5e-4 c 2.49605748,4.9921 4.18258278,-0.1349 4.18258278,-0.1349 l 0.023851,0 c 2.7659014,5.5993 4.0912704,0 4.0912704,0 l 0.02385,0 c 3.1706688,5.9366 4.2936548,0 4.2936548,0"
+ id="path4893-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 3.7221911,1045.5303 c 2.5635186,5.7342 4.4524269,0.068 4.4524269,0.068 l 0.067461,-5e-4 c 2.496057,4.9921 4.182583,-0.1349 4.182583,-0.1349 l 0.02385,0 c 2.765901,5.5993 4.09127,0 4.09127,0 l 0.02385,0 c 3.170668,5.9366 4.293654,0 4.293654,0"
+ id="path4893-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -3.5762361,1049.3465 c 2.5635185,5.7342 4.4524268,0.068 4.4524268,0.068 l 0.067461,-5e-4 c 2.4960575,4.9921 4.1825828,-0.1349 4.1825828,-0.1349 l 0.023851,0 c 2.7659014,5.5993 4.0912702,0 4.0912702,0 l 0.02385,0 c 3.1706683,5.9366 4.2936543,0 4.2936543,0"
+ id="path4893-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ </g>
+</svg>
diff --git a/platform/macos/app/resources/circle.svg b/platform/macos/app/resources/circle.svg
new file mode 100644
index 0000000000..91e0b11990
--- /dev/null
+++ b/platform/macos/app/resources/circle.svg
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ id="svg4148"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="circle.svg"
+ inkscape:export-filename="/Users/mxn/Desktop/symbol.png"
+ inkscape:export-xdpi="90.000244"
+ inkscape:export-ydpi="90.000244">
+ <defs
+ id="defs4150" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="7.9195959"
+ inkscape:cx="3.8463784"
+ inkscape:cy="-0.92094419"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:window-width="1280"
+ inkscape:window-height="751"
+ inkscape:window-x="0"
+ inkscape:window-y="1"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata4153">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <circle
+ style="opacity:1;fill:none;fill-opacity:0;fill-rule:evenodd;stroke:#000000;stroke-width:1.49974895;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path4778"
+ cx="8"
+ cy="1044.3622"
+ r="7.2501254" />
+ </g>
+</svg>
diff --git a/platform/macos/app/resources/fill.svg b/platform/macos/app/resources/fill.svg
new file mode 100644
index 0000000000..7860a5fddb
--- /dev/null
+++ b/platform/macos/app/resources/fill.svg
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ id="svg4148"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="fill.svg"
+ inkscape:export-filename="/Users/mxn/Desktop/symbol.png"
+ inkscape:export-xdpi="90.000244"
+ inkscape:export-ydpi="90.000244">
+ <defs
+ id="defs4150" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="7.9195959"
+ inkscape:cx="0.31084444"
+ inkscape:cy="-0.92094419"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:window-width="1280"
+ inkscape:window-height="751"
+ inkscape:window-x="0"
+ inkscape:window-y="1"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata4153">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <rect
+ style="opacity:1;fill:#000000;fill-opacity:0.15686275;fill-rule:evenodd;stroke:#000000;stroke-width:1.37142861;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect4818"
+ width="14.628572"
+ height="14.628572"
+ x="0.68571424"
+ y="1037.048" />
+ </g>
+</svg>
diff --git a/platform/macos/app/resources/symbol.svg b/platform/macos/app/resources/symbol.svg
new file mode 100644
index 0000000000..68847cb50f
--- /dev/null
+++ b/platform/macos/app/resources/symbol.svg
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ id="svg4148"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="symbol.svg"
+ inkscape:export-filename="/Users/mxn/Desktop/symbol.png"
+ inkscape:export-xdpi="90.000244"
+ inkscape:export-ydpi="90.000244">
+ <defs
+ id="defs4150" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="7.9195959"
+ inkscape:cx="3.8463784"
+ inkscape:cy="-0.92094419"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:window-width="1280"
+ inkscape:window-height="751"
+ inkscape:window-x="0"
+ inkscape:window-y="1"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata4153">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;stroke-width:1.45454013;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5359"
+ d="m 13.062591,1042.4228 c 0,3.394 -5.0625908,9.2122 -5.0625908,9.2122 0,0 -5.0625898,-5.872 -5.0625898,-9.2122 0,-2.9629 2.2914879,-5.3333 5.0625898,-5.3333 2.7711018,0 5.0625908,2.3704 5.0625908,5.3333 z" />
+ </g>
+</svg>
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index 3ab9d4d9c0..0c28691cb4 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -115,6 +115,7 @@
DA8F259C1D51CB000010E6B5 /* MGLStyleValue_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8F259B1D51CB000010E6B5 /* MGLStyleValue_Private.h */; };
DA8F25B21D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8F25A61D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h */; };
DA8F25B31D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25A71D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm */; };
+ DAA48EFD1D6A4731006A7E36 /* StyleLayerIconTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA48EFC1D6A4731006A7E36 /* StyleLayerIconTransformer.m */; };
DAC2ABC51CC6D343006D18C4 /* MGLAnnotationImage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */; };
DACC22141CF3D3E200D220D9 /* MGLFeature.h in Headers */ = {isa = PBXBuildFile; fileRef = DACC22121CF3D3E200D220D9 /* MGLFeature.h */; settings = {ATTRIBUTES = (Public, ); }; };
DACC22151CF3D3E200D220D9 /* MGLFeature.mm in Sources */ = {isa = PBXBuildFile; fileRef = DACC22131CF3D3E200D220D9 /* MGLFeature.mm */; };
@@ -356,6 +357,8 @@
DA8F25B51D51D2240010E6B5 /* MGLRuntimeStylingTests.m.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLRuntimeStylingTests.m.ejs; sourceTree = "<group>"; };
DA8F25B61D51D2240010E6B5 /* MGLStyleLayer.h.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLStyleLayer.h.ejs; sourceTree = "<group>"; };
DA8F25B71D51D2240010E6B5 /* MGLStyleLayer.mm.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLStyleLayer.mm.ejs; sourceTree = "<group>"; };
+ DAA48EFB1D6A4731006A7E36 /* StyleLayerIconTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleLayerIconTransformer.h; sourceTree = "<group>"; };
+ DAA48EFC1D6A4731006A7E36 /* StyleLayerIconTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StyleLayerIconTransformer.m; sourceTree = "<group>"; };
DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationImage_Private.h; sourceTree = "<group>"; };
DACC22121CF3D3E200D220D9 /* MGLFeature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFeature.h; sourceTree = "<group>"; };
DACC22131CF3D3E200D220D9 /* MGLFeature.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFeature.mm; sourceTree = "<group>"; };
@@ -588,6 +591,8 @@
DA839E9E1CC2E3400062CAFB /* MapDocument.xib */,
DAE6C2E91CC3050F00DB3429 /* OfflinePackNameValueTransformer.h */,
DAE6C2EA1CC3050F00DB3429 /* OfflinePackNameValueTransformer.m */,
+ DAA48EFB1D6A4731006A7E36 /* StyleLayerIconTransformer.h */,
+ DAA48EFC1D6A4731006A7E36 /* StyleLayerIconTransformer.m */,
DAE6C2EB1CC3050F00DB3429 /* TimeIntervalTransformer.h */,
DAE6C2EC1CC3050F00DB3429 /* TimeIntervalTransformer.m */,
DA839EA11CC2E3400062CAFB /* Assets.xcassets */,
@@ -1156,6 +1161,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ DAA48EFD1D6A4731006A7E36 /* StyleLayerIconTransformer.m in Sources */,
DA839E9D1CC2E3400062CAFB /* MapDocument.m in Sources */,
DAE6C2ED1CC3050F00DB3429 /* DroppedPinAnnotation.m in Sources */,
DAE6C2EE1CC3050F00DB3429 /* LocationCoordinate2DTransformer.m in Sources */,