| // Copyright 2018 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. |
| |
| import 'dart:ui' show hashValues, Offset; |
| |
| import 'package:flutter/foundation.dart' show ValueChanged, VoidCallback; |
| import 'package:meta/meta.dart' show immutable, required; |
| |
| import 'types.dart'; |
| |
| dynamic _offsetToJson(Offset offset) { |
| if (offset == null) { |
| return null; |
| } |
| return <dynamic>[offset.dx, offset.dy]; |
| } |
| |
| /// Text labels for a [Marker] info window. |
| class InfoWindow { |
| /// Creates an immutable representation of a label on for [Marker]. |
| const InfoWindow({ |
| this.title, |
| this.snippet, |
| this.anchor = const Offset(0.5, 0.0), |
| this.onTap, |
| }); |
| |
| /// Text labels specifying that no text is to be displayed. |
| static const InfoWindow noText = InfoWindow(); |
| |
| /// Text displayed in an info window when the user taps the marker. |
| /// |
| /// A null value means no title. |
| final String title; |
| |
| /// Additional text displayed below the [title]. |
| /// |
| /// A null value means no additional text. |
| final String snippet; |
| |
| /// The icon image point that will be the anchor of the info window when |
| /// displayed. |
| /// |
| /// The image point is specified in normalized coordinates: An anchor of |
| /// (0.0, 0.0) means the top left corner of the image. An anchor |
| /// of (1.0, 1.0) means the bottom right corner of the image. |
| final Offset anchor; |
| |
| /// onTap callback for this [InfoWindow]. |
| final VoidCallback onTap; |
| |
| /// Creates a new [InfoWindow] object whose values are the same as this instance, |
| /// unless overwritten by the specified parameters. |
| InfoWindow copyWith({ |
| String titleParam, |
| String snippetParam, |
| Offset anchorParam, |
| VoidCallback onTapParam, |
| }) { |
| return InfoWindow( |
| title: titleParam ?? title, |
| snippet: snippetParam ?? snippet, |
| anchor: anchorParam ?? anchor, |
| onTap: onTapParam ?? onTap, |
| ); |
| } |
| |
| dynamic _toJson() { |
| final Map<String, dynamic> json = <String, dynamic>{}; |
| |
| void addIfPresent(String fieldName, dynamic value) { |
| if (value != null) { |
| json[fieldName] = value; |
| } |
| } |
| |
| addIfPresent('title', title); |
| addIfPresent('snippet', snippet); |
| addIfPresent('anchor', _offsetToJson(anchor)); |
| |
| return json; |
| } |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(this, other)) return true; |
| if (other.runtimeType != runtimeType) return false; |
| final InfoWindow typedOther = other; |
| return title == typedOther.title && |
| snippet == typedOther.snippet && |
| anchor == typedOther.anchor; |
| } |
| |
| @override |
| int get hashCode => hashValues(title.hashCode, snippet, anchor); |
| |
| @override |
| String toString() { |
| return 'InfoWindow{title: $title, snippet: $snippet, anchor: $anchor}'; |
| } |
| } |
| |
| /// Uniquely identifies a [Marker] among [GoogleMap] markers. |
| /// |
| /// This does not have to be globally unique, only unique among the list. |
| @immutable |
| class MarkerId { |
| /// Creates an immutable identifier for a [Marker]. |
| MarkerId(this.value) : assert(value != null); |
| |
| /// value of the [MarkerId]. |
| final String value; |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(this, other)) return true; |
| if (other.runtimeType != runtimeType) return false; |
| final MarkerId typedOther = other; |
| return value == typedOther.value; |
| } |
| |
| @override |
| int get hashCode => value.hashCode; |
| |
| @override |
| String toString() { |
| return 'MarkerId{value: $value}'; |
| } |
| } |
| |
| /// Marks a geographical location on the map. |
| /// |
| /// A marker icon is drawn oriented against the device's screen rather than |
| /// the map's surface; that is, it will not necessarily change orientation |
| /// due to map rotations, tilting, or zooming. |
| @immutable |
| class Marker { |
| /// Creates a set of marker configuration options. |
| /// |
| /// Default marker options. |
| /// |
| /// Specifies a marker that |
| /// * is fully opaque; [alpha] is 1.0 |
| /// * uses icon bottom center to indicate map position; [anchor] is (0.5, 1.0) |
| /// * has default tap handling; [consumeTapEvents] is false |
| /// * is stationary; [draggable] is false |
| /// * is drawn against the screen, not the map; [flat] is false |
| /// * has a default icon; [icon] is `BitmapDescriptor.defaultMarker` |
| /// * anchors the info window at top center; [infoWindowAnchor] is (0.5, 0.0) |
| /// * has no info window text; [infoWindowText] is `InfoWindowText.noText` |
| /// * is positioned at 0, 0; [position] is `LatLng(0.0, 0.0)` |
| /// * has an axis-aligned icon; [rotation] is 0.0 |
| /// * is visible; [visible] is true |
| /// * is placed at the base of the drawing order; [zIndex] is 0.0 |
| /// * reports [onTap] events |
| /// * reports [onDragEnd] events |
| const Marker({ |
| @required this.markerId, |
| this.alpha = 1.0, |
| this.anchor = const Offset(0.5, 1.0), |
| this.consumeTapEvents = false, |
| this.draggable = false, |
| this.flat = false, |
| this.icon = BitmapDescriptor.defaultMarker, |
| this.infoWindow = InfoWindow.noText, |
| this.position = const LatLng(0.0, 0.0), |
| this.rotation = 0.0, |
| this.visible = true, |
| this.zIndex = 0.0, |
| this.onTap, |
| this.onDragEnd, |
| }) : assert(alpha == null || (0.0 <= alpha && alpha <= 1.0)); |
| |
| /// Uniquely identifies a [Marker]. |
| final MarkerId markerId; |
| |
| /// The opacity of the marker, between 0.0 and 1.0 inclusive. |
| /// |
| /// 0.0 means fully transparent, 1.0 means fully opaque. |
| final double alpha; |
| |
| /// The icon image point that will be placed at the [position] of the marker. |
| /// |
| /// The image point is specified in normalized coordinates: An anchor of |
| /// (0.0, 0.0) means the top left corner of the image. An anchor |
| /// of (1.0, 1.0) means the bottom right corner of the image. |
| final Offset anchor; |
| |
| /// True if the marker icon consumes tap events. If not, the map will perform |
| /// default tap handling by centering the map on the marker and displaying its |
| /// info window. |
| final bool consumeTapEvents; |
| |
| /// True if the marker is draggable by user touch events. |
| final bool draggable; |
| |
| /// True if the marker is rendered flatly against the surface of the Earth, so |
| /// that it will rotate and tilt along with map camera movements. |
| final bool flat; |
| |
| /// A description of the bitmap used to draw the marker icon. |
| final BitmapDescriptor icon; |
| |
| /// A Google Maps InfoWindow. |
| /// |
| /// The window is displayed when the marker is tapped. |
| final InfoWindow infoWindow; |
| |
| /// Geographical location of the marker. |
| final LatLng position; |
| |
| /// Rotation of the marker image in degrees clockwise from the [anchor] point. |
| final double rotation; |
| |
| /// True if the marker is visible. |
| final bool visible; |
| |
| /// The z-index of the marker, 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 double zIndex; |
| |
| /// Callbacks to receive tap events for markers placed on this map. |
| final VoidCallback onTap; |
| |
| /// Signature reporting the new [LatLng] at the end of a drag event. |
| final ValueChanged<LatLng> onDragEnd; |
| |
| /// Creates a new [Marker] object whose values are the same as this instance, |
| /// unless overwritten by the specified parameters. |
| Marker copyWith({ |
| double alphaParam, |
| Offset anchorParam, |
| bool consumeTapEventsParam, |
| bool draggableParam, |
| bool flatParam, |
| BitmapDescriptor iconParam, |
| InfoWindow infoWindowParam, |
| LatLng positionParam, |
| double rotationParam, |
| bool visibleParam, |
| double zIndexParam, |
| VoidCallback onTapParam, |
| ValueChanged<LatLng> onDragEndParam, |
| }) { |
| return Marker( |
| markerId: markerId, |
| alpha: alphaParam ?? alpha, |
| anchor: anchorParam ?? anchor, |
| consumeTapEvents: consumeTapEventsParam ?? consumeTapEvents, |
| draggable: draggableParam ?? draggable, |
| flat: flatParam ?? flat, |
| icon: iconParam ?? icon, |
| infoWindow: infoWindowParam ?? infoWindow, |
| position: positionParam ?? position, |
| rotation: rotationParam ?? rotation, |
| visible: visibleParam ?? visible, |
| zIndex: zIndexParam ?? zIndex, |
| onTap: onTapParam ?? onTap, |
| onDragEnd: onDragEndParam ?? onDragEnd, |
| ); |
| } |
| |
| /// Creates a new [Marker] object whose values are the same as this instance. |
| Marker clone() => copyWith(); |
| |
| /// Converts this object to something serializable in JSON. |
| Map<String, dynamic> toJson() { |
| final Map<String, dynamic> json = <String, dynamic>{}; |
| |
| void addIfPresent(String fieldName, dynamic value) { |
| if (value != null) { |
| json[fieldName] = value; |
| } |
| } |
| |
| addIfPresent('markerId', markerId.value); |
| addIfPresent('alpha', alpha); |
| addIfPresent('anchor', _offsetToJson(anchor)); |
| addIfPresent('consumeTapEvents', consumeTapEvents); |
| addIfPresent('draggable', draggable); |
| addIfPresent('flat', flat); |
| addIfPresent('icon', icon?.toJson()); |
| addIfPresent('infoWindow', infoWindow?._toJson()); |
| addIfPresent('position', position?.toJson()); |
| addIfPresent('rotation', rotation); |
| addIfPresent('visible', visible); |
| addIfPresent('zIndex', zIndex); |
| return json; |
| } |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(this, other)) return true; |
| if (other.runtimeType != runtimeType) return false; |
| final Marker typedOther = other; |
| return markerId == typedOther.markerId && |
| alpha == typedOther.alpha && |
| anchor == typedOther.anchor && |
| consumeTapEvents == typedOther.consumeTapEvents && |
| draggable == typedOther.draggable && |
| flat == typedOther.flat && |
| icon == typedOther.icon && |
| infoWindow == typedOther.infoWindow && |
| position == typedOther.position && |
| rotation == typedOther.rotation && |
| visible == typedOther.visible && |
| zIndex == typedOther.zIndex; |
| } |
| |
| @override |
| int get hashCode => markerId.hashCode; |
| |
| @override |
| String toString() { |
| return 'Marker{markerId: $markerId, alpha: $alpha, anchor: $anchor, ' |
| 'consumeTapEvents: $consumeTapEvents, draggable: $draggable, flat: $flat, ' |
| 'icon: $icon, infoWindow: $infoWindow, position: $position, rotation: $rotation, ' |
| 'visible: $visible, zIndex: $zIndex, onTap: $onTap}'; |
| } |
| } |