| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| part of google_maps_flutter; |
| |
| /// Uniquely identifies a [Polyline] among [GoogleMap] polylines. |
| /// |
| /// This does not have to be globally unique, only unique among the list. |
| @immutable |
| class PolylineId { |
| PolylineId(this.value) : assert(value != null); |
| |
| /// value of the [PolylineId]. |
| final String value; |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(this, other)) return true; |
| if (other.runtimeType != runtimeType) return false; |
| final PolylineId typedOther = other; |
| return value == typedOther.value; |
| } |
| |
| @override |
| int get hashCode => value.hashCode; |
| |
| @override |
| String toString() { |
| return 'PolylineId{value: $value}'; |
| } |
| } |
| |
| /// Draws a line through geographical locations on the map. |
| @immutable |
| class Polyline { |
| const Polyline({ |
| @required this.polylineId, |
| this.consumeTapEvents = false, |
| this.color = Colors.black, |
| this.endCap = Cap.buttCap, |
| this.geodesic = false, |
| this.jointType = JointType.mitered, |
| this.points = const <LatLng>[], |
| this.patterns = const <PatternItem>[], |
| this.startCap = Cap.buttCap, |
| this.visible = true, |
| this.width = 10, |
| this.zIndex = 0, |
| this.onTap, |
| }); |
| |
| /// Uniquely identifies a [Polyline]. |
| final PolylineId polylineId; |
| |
| /// True if the [Polyline] consumes tap events. |
| /// |
| /// If this is false, [onTap] callback will not be triggered. |
| final bool consumeTapEvents; |
| |
| /// Line segment color in ARGB format, the same format used by Color. The default value is black (0xff000000). |
| final Color color; |
| |
| /// Indicates whether the segments of the polyline should be drawn as geodesics, as opposed to straight lines |
| /// on the Mercator projection. |
| /// |
| /// A geodesic is the shortest path between two points on the Earth's surface. |
| /// The geodesic curve is constructed assuming the Earth is a sphere |
| final bool geodesic; |
| |
| /// Joint type of the polyline line segments. |
| /// |
| /// The joint type defines the shape to be used when joining adjacent line segments at all vertices of the |
| /// polyline except the start and end vertices. See [JointType] for supported joint types. The default value is |
| /// mitered. |
| /// |
| /// Supported on Android only. |
| final JointType jointType; |
| |
| /// The stroke pattern for the polyline. |
| /// |
| /// Solid or a sequence of PatternItem objects to be repeated along the line. |
| /// Available PatternItem types: Gap (defined by gap length in pixels), Dash (defined by line width and dash |
| /// length in pixels) and Dot (circular, centered on the line, diameter defined by line width in pixels). |
| final List<PatternItem> patterns; |
| |
| /// The vertices of the polyline to be drawn. |
| /// |
| /// Line segments are drawn between consecutive points. A polyline is not closed by |
| /// default; to form a closed polyline, the start and end points must be the same. |
| final List<LatLng> points; |
| |
| /// The cap at the start vertex of the polyline. |
| /// |
| /// The default start cap is ButtCap. |
| /// |
| /// Supported on Android only. |
| final Cap startCap; |
| |
| /// The cap at the end vertex of the polyline. |
| /// |
| /// The default end cap is ButtCap. |
| /// |
| /// Supported on Android only. |
| final Cap endCap; |
| |
| /// True if the marker is visible. |
| final bool visible; |
| |
| /// Width of the polyline, used to define the width of the line segment to be drawn. |
| /// |
| /// The width is constant and independent of the camera's zoom level. |
| /// The default value is 10. |
| final int width; |
| |
| /// The z-index of the polyline, used to determine relative drawing order of |
| /// map overlays. |
| /// |
| /// Overlays are drawn in order of z-index, so that lower values means drawn |
| /// earlier, and thus appearing to be closer to the surface of the Earth. |
| final int zIndex; |
| |
| /// Callbacks to receive tap events for polyline placed on this map. |
| final VoidCallback onTap; |
| |
| /// Creates a new [Polyline] object whose values are the same as this instance, |
| /// unless overwritten by the specified parameters. |
| Polyline copyWith({ |
| Color colorParam, |
| bool consumeTapEventsParam, |
| Cap endCapParam, |
| bool geodesicParam, |
| JointType jointTypeParam, |
| List<PatternItem> patternsParam, |
| List<LatLng> pointsParam, |
| Cap startCapParam, |
| bool visibleParam, |
| int widthParam, |
| int zIndexParam, |
| VoidCallback onTapParam, |
| }) { |
| return Polyline( |
| polylineId: polylineId, |
| color: colorParam ?? color, |
| consumeTapEvents: consumeTapEventsParam ?? consumeTapEvents, |
| endCap: endCapParam ?? endCap, |
| geodesic: geodesicParam ?? geodesic, |
| jointType: jointTypeParam ?? jointType, |
| patterns: patternsParam ?? patterns, |
| points: pointsParam ?? points, |
| startCap: startCapParam ?? startCap, |
| visible: visibleParam ?? visible, |
| width: widthParam ?? width, |
| onTap: onTapParam ?? onTap, |
| zIndex: zIndexParam ?? zIndex, |
| ); |
| } |
| |
| /// Creates a new [Polyline] object whose values are the same as this |
| /// instance. |
| Polyline clone() { |
| return copyWith( |
| patternsParam: List<PatternItem>.of(patterns), |
| pointsParam: List<LatLng>.of(points), |
| ); |
| } |
| |
| dynamic _toJson() { |
| final Map<String, dynamic> json = <String, dynamic>{}; |
| |
| void addIfPresent(String fieldName, dynamic value) { |
| if (value != null) { |
| json[fieldName] = value; |
| } |
| } |
| |
| addIfPresent('polylineId', polylineId.value); |
| addIfPresent('consumeTapEvents', consumeTapEvents); |
| addIfPresent('color', color.value); |
| addIfPresent('endCap', endCap?._toJson()); |
| addIfPresent('geodesic', geodesic); |
| addIfPresent('jointType', jointType?.value); |
| addIfPresent('startCap', startCap?._toJson()); |
| addIfPresent('visible', visible); |
| addIfPresent('width', width); |
| addIfPresent('zIndex', zIndex); |
| |
| if (points != null) { |
| json['points'] = _pointsToJson(); |
| } |
| |
| if (patterns != null) { |
| json['pattern'] = _patternToJson(); |
| } |
| |
| return json; |
| } |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(this, other)) return true; |
| if (other.runtimeType != runtimeType) return false; |
| final Polyline typedOther = other; |
| return polylineId == typedOther.polylineId && |
| consumeTapEvents == typedOther.consumeTapEvents && |
| color == typedOther.color && |
| geodesic == typedOther.geodesic && |
| jointType == typedOther.jointType && |
| listEquals(patterns, typedOther.patterns) && |
| listEquals(points, typedOther.points) && |
| startCap == typedOther.startCap && |
| endCap == typedOther.endCap && |
| visible == typedOther.visible && |
| width == typedOther.width && |
| zIndex == typedOther.zIndex && |
| onTap == typedOther.onTap; |
| } |
| |
| @override |
| int get hashCode => polylineId.hashCode; |
| |
| dynamic _pointsToJson() { |
| final List<dynamic> result = <dynamic>[]; |
| for (final LatLng point in points) { |
| result.add(point._toJson()); |
| } |
| return result; |
| } |
| |
| dynamic _patternToJson() { |
| final List<dynamic> result = <dynamic>[]; |
| for (final PatternItem patternItem in patterns) { |
| if (patternItem != null) { |
| result.add(patternItem._toJson()); |
| } |
| } |
| return result; |
| } |
| } |
| |
| Map<PolylineId, Polyline> _keyByPolylineId(Iterable<Polyline> polylines) { |
| if (polylines == null) { |
| return <PolylineId, Polyline>{}; |
| } |
| return Map<PolylineId, Polyline>.fromEntries(polylines.map( |
| (Polyline polyline) => MapEntry<PolylineId, Polyline>( |
| polyline.polylineId, polyline.clone()))); |
| } |
| |
| List<Map<String, dynamic>> _serializePolylineSet(Set<Polyline> polylines) { |
| if (polylines == null) { |
| return null; |
| } |
| return polylines |
| .map<Map<String, dynamic>>((Polyline p) => p._toJson()) |
| .toList(); |
| } |