Save bookmarks viewport scale when adding.

This commit is contained in:
vng 2012-10-10 19:05:27 +03:00 committed by Alex Zolotarev
parent 79c59a474a
commit 12b8678ae3
6 changed files with 134 additions and 77 deletions

View file

@ -6,8 +6,8 @@
#import "CompassView.h"
#include "Framework.h"
#include "../../../geometry/distance_on_sphere.hpp"
#include "../../../platform/platform.hpp"
@implementation BookmarksVC
@ -48,7 +48,7 @@
{
BookmarkCategory * cat = GetFramework().GetBmCategory(m_categoryIndex);
cat->SetVisible(sender.on);
cat->SaveToKMLFileAtPath(GetPlatform().WritableDir());
cat->SaveToKMLFile();
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
@ -153,7 +153,7 @@
else
{
Framework & f = GetFramework();
BookmarkCategory * cat = f.GetBmCategory(m_categoryIndex);
BookmarkCategory const * cat = f.GetBmCategory(m_categoryIndex);
if (cat)
{
Bookmark const * bm = cat->GetBookmark(indexPath.row);
@ -162,7 +162,7 @@
// Same as "Close".
[self dismissModalViewControllerAnimated:YES];
[self.navigationController.visibleViewController dismissModalViewControllerAnimated:YES];
f.ShowRectExVisibleScale(bm->GetViewport());
f.ShowBookmark(*bm);
}
}
}

View file

@ -2,11 +2,10 @@
#include "../indexer/mercator.hpp"
#include "../platform/platform.hpp"
#include "../coding/file_reader.hpp"
#include "../coding/parse_xml.hpp" // LoadFromKML
#include "../base/string_utils.hpp"
#include "../platform/platform.hpp"
#include "../base/stl_add.hpp"
#include "../base/string_utils.hpp"
@ -15,19 +14,30 @@
#include "../std/algorithm.hpp"
void BookmarkCategory::AddBookmark(Bookmark const & bm)
void BookmarkCategory::AddBookmark(Bookmark const & bm, double scale)
{
m_bookmarks.push_back(new Bookmark(bm));
Bookmark * p = new Bookmark(bm);
p->SetScale(scale);
m_bookmarks.push_back(p);
VERIFY ( SaveToKMLFile(), () );
}
void BookmarkCategory::ReplaceBookmark(size_t index, Bookmark const & bm)
void BookmarkCategory::ReplaceBookmark(size_t index, Bookmark const & bm, double scale)
{
ASSERT_LESS(index, m_bookmarks.size(), ());
ASSERT_LESS ( index, m_bookmarks.size(), () );
if (index < m_bookmarks.size())
{
Bookmark * p = new Bookmark(bm);
p->SetScale(scale);
Bookmark const * old = m_bookmarks[index];
m_bookmarks[index] = new Bookmark(bm);
m_bookmarks[index] = p;
delete old;
VERIFY ( SaveToKMLFile(), () );
}
else
LOG(LWARNING, ("Trying to replace non-existing bookmark"));
@ -50,9 +60,8 @@ void BookmarkCategory::DeleteBookmark(size_t index)
{
delete m_bookmarks[index];
m_bookmarks.erase(m_bookmarks.begin() + index);
// Save updated file
if (!m_file.empty())
(void)SaveToKMLFileAtPath(m_file);
VERIFY ( SaveToKMLFile(), () );
}
else
{
@ -80,17 +89,20 @@ namespace
// Fixes icons which are not supported by MapsWithMe
static string GetSupportedBMType(string const & s)
{
static char const * icons[] = {"placemark-red", "placemark-blue", "placemark-purple",
"placemark-pink", "placemark-brown", "placemark-green", "placemark-orange"};
static char const * icons[] = {
"placemark-red", "placemark-blue", "placemark-purple",
"placemark-pink", "placemark-brown", "placemark-green", "placemark-orange"
};
// Remove leading '#' symbol
string result = s.substr(1);
string const result = s.substr(1);
for (size_t i = 0; i < ARRAY_SIZE(icons); ++i)
if (result == icons[i])
return result;
// Not recognized symbols are replaced with default one
LOG(LWARNING, ("Bookmark icon is not supported:", result));
return "placemark-red";
return icons[0];
}
class KMLParser
@ -103,12 +115,14 @@ namespace
string m_type;
m2::PointD m_org;
double m_scale;
void Reset()
{
m_name.clear();
m_org = m2::PointD(-1000, -1000);
m_type.clear();
m_scale = -1.0;
}
void SetOrigin(string const & s)
@ -156,43 +170,49 @@ namespace
if (tag == "Placemark" && IsValid())
{
m_category.AddBookmark(Bookmark(m_org, m_name, m_type));
m_category.AddBookmark(Bookmark(m_org, m_name, m_type), m_scale);
Reset();
}
m_tags.pop_back();
}
class IsSpace
{
public:
bool operator() (char c) const
{
return ::isspace(c);
}
};
void CharData(string value)
{
strings::Trim(value);
size_t const count = m_tags.size();
if (count > 1 && !value.empty())
{
string const & currTag = m_tags[count - 1];
string const & prevTag = m_tags[count - 2];
if (currTag == "name")
if (prevTag == "Document")
{
if (prevTag == "Placemark")
m_name = value;
else if (prevTag == "Document")
if (currTag == "name")
m_category.SetName(value);
else if (currTag == "visibility")
m_category.SetVisible(value == "0" ? false : true);
}
else if (prevTag == "Placemark")
{
if (currTag == "name")
m_name = value;
else if (currTag == "styleUrl")
m_type = GetSupportedBMType(value);
}
else if (prevTag == "Point")
{
if (currTag == "coordinates")
SetOrigin(value);
}
else if (prevTag == "ExtendedData")
{
if (currTag == "mwm:scale")
{
if (!strings::to_double(value, m_scale))
m_scale = -1.0;
}
}
else if (currTag == "coordinates" && prevTag == "Point")
SetOrigin(value);
else if (currTag == "visibility" && prevTag == "Document")
m_category.SetVisible(value == "0" ? false : true);
else if (currTag == "styleUrl" && prevTag == "Placemark")
m_type = GetSupportedBMType(value);
}
}
};
@ -312,8 +332,18 @@ void BookmarkCategory::SaveToKML(ostream & s)
<< " <styleUrl>#" << bm->GetType() << "</styleUrl>\n"
<< " <Point>\n"
<< " <coordinates>" << PointToString(bm->GetOrg()) << "</coordinates>\n"
<< " </Point>\n"
<< " </Placemark>\n";
<< " </Point>\n";
double const scale = bm->GetScale();
if (scale != -1)
{
/// @todo Factor out to separate function to use for other custom params.
s << " <ExtendedData xmlns:mwm=\"http://mapswithme.com\">\n"
<< " <mwm:scale>" << bm->GetScale() << "</mwm:scale>\n"
<< " </ExtendedData>\n";
}
s << " </Placemark>\n";
}
s << kmlFooter;
@ -346,10 +376,13 @@ string BookmarkCategory::GenerateUniqueFileName(const string & path, string cons
return path + fixedName + suffix + ".kml";
}
bool BookmarkCategory::SaveToKMLFileAtPath(string const & path)
bool BookmarkCategory::SaveToKMLFile()
{
if (m_file.empty())
m_file = GenerateUniqueFileName(path, m_file);
{
/// @todo It's better to pass category name as file name here, isn't it?
m_file = GenerateUniqueFileName(GetPlatform().WritableDir(), m_file);
}
try
{

View file

@ -14,8 +14,8 @@ class Bookmark
{
m2::PointD m_org;
string m_name;
/// Now it stores bookmark color
string m_type;
string m_type; ///< Now it stores bookmark color (category style).
double m_scale; ///< Viewport scale. -1.0 - is a default value (no scale set).
public:
Bookmark() {}
@ -26,9 +26,12 @@ public:
m2::PointD GetOrg() const { return m_org; }
string const & GetName() const { return m_name; }
/// Now it returns bookmark color
/// @return Now its a bookmark color.
string const & GetType() const { return m_type; }
m2::RectD GetViewport() const { return m2::RectD(m_org, m_org); }
double GetScale() const { return m_scale; }
void SetScale(double scale) { m_scale = scale; }
};
class BookmarkCategory : private noncopyable
@ -45,32 +48,43 @@ public:
void ClearBookmarks();
void AddBookmark(Bookmark const & bm);
/// @name This function are called from Framework only.
//@{
void AddBookmark(Bookmark const & bm, double scale);
void ReplaceBookmark(size_t index, Bookmark const & bm, double scale);
//@}
void SetVisible(bool isVisible) { m_visible = isVisible; }
bool IsVisible() const { return m_visible; }
void SetName(string const & name) { m_name = name; }
string GetName() const { return m_name; }
string GetFileName() const { return m_file; }
inline size_t GetBookmarksCount() const { return m_bookmarks.size(); }
Bookmark const * GetBookmark(size_t index) const;
/// @param[in] distance in metres between orgs
/// @returns -1 or index of found bookmark
int GetBookmark(m2::PointD const org, double const squareDistance) const;
void DeleteBookmark(size_t index);
void ReplaceBookmark(size_t index, Bookmark const & bm);
void DeleteBookmark(size_t index);
/// @name This fuctions are public for unit tests only.
/// You don't need to call them from client code.
//@{
void LoadFromKML(ReaderPtr<Reader> const & reader);
void SaveToKML(ostream & s);
/// Uses the same file name from which was loaded, or
/// creates unique file name on first save and uses it every time.
bool SaveToKMLFile();
/// @return 0 in the case of error
static BookmarkCategory * CreateFromKMLFile(string const & file);
/// Uses the same file name from which was loaded, or
/// creates unique file name on first save and uses it every time
/// @param[in] path directory name where to save
bool SaveToKMLFileAtPath(string const & path);
static string GenerateUniqueFileName(const string & path, string const & name);
//@}
};
/// <category index, bookmark index>

View file

@ -221,6 +221,11 @@ Framework::~Framework()
ClearBookmarks();
}
double Framework::GetVisualScale() const
{
return (m_renderPolicy ? m_renderPolicy->VisualScale() : 1);
}
void Framework::DeleteCountry(TIndex const & index)
{
if (!m_storage.DeleteFromDownloader(index))
@ -321,6 +326,10 @@ void Framework::LoadBookmarks()
void Framework::AddBookmark(string const & category, Bookmark const & bm)
{
// Get global non-rotated viewport rect and calculate viewport scale level.
double const scale = scales::GetScaleLevelD(
m_navigator.Screen().GlobalRect().GetLocalRect());
// @TODO not optimal for 1st release
// Existing bookmark can be moved from one category to another,
// or simply replaced in the same category,
@ -330,15 +339,13 @@ void Framework::AddBookmark(string const & category, Bookmark const & bm)
{
m2::PointD const org = bm.GetOrg();
BookmarkCategory * cat = m_bookmarks[i];
int index = cat->GetBookmark(org, squareDistance);
int const index = cat->GetBookmark(org, squareDistance);
if (index >= 0)
{
// found bookmark to replace
if (category == cat->GetName())
{
cat->ReplaceBookmark(static_cast<size_t>(index), bm);
// Autosave added bookmark
(void)cat->SaveToKMLFileAtPath(GetPlatform().WritableDir());
cat->ReplaceBookmark(static_cast<size_t>(index), bm, scale);
return;
}
else
@ -350,10 +357,7 @@ void Framework::AddBookmark(string const & category, Bookmark const & bm)
}
BookmarkCategory * cat = GetBmCategory(category);
ASSERT(cat, ("category should autocreate if not exists"));
cat->AddBookmark(bm);
// Autosave added bookmark
(void)cat->SaveToKMLFileAtPath(GetPlatform().WritableDir());
cat->AddBookmark(bm, scale);
}
namespace
@ -403,15 +407,12 @@ bool Framework::DeleteBmCategory(size_t index)
else return false;
}
BookmarkAndCategory Framework::GetBookmark(m2::PointD pt) const
BookmarkAndCategory Framework::GetBookmark(m2::PointD const & pxPoint) const
{
// @TODO Refactor. Why bookmarks can't be retrieved? Change pixel point to global point.
if (m_renderPolicy == 0)
return MakeEmptyBookmarkAndCategory();
return GetBookmark(pt, m_renderPolicy->VisualScale());
return GetBookmark(pxPoint, GetVisualScale());
}
BookmarkAndCategory Framework::GetBookmark(m2::PointD pxPoint, double visualScale) const
BookmarkAndCategory Framework::GetBookmark(m2::PointD const & pxPoint, double visualScale) const
{
// Get the global rect of touching area.
int const sm = TOUCH_PIXEL_RADIUS * visualScale;
@ -446,6 +447,14 @@ BookmarkAndCategory Framework::GetBookmark(m2::PointD pxPoint, double visualScal
return make_pair(retBookmarkCategory, retBookmark);
}
void Framework::ShowBookmark(Bookmark const & bm)
{
double scale = bm.GetScale();
if (scale == -1.0) scale = 16.0;
ShowRectExVisibleScale(scales::GetRectForLevel(scale, bm.GetOrg(), 1.0));
}
void Framework::ClearBookmarks()
{
for_each(m_bookmarks.begin(), m_bookmarks.end(), DeleteFunctor());
@ -1346,14 +1355,8 @@ shared_ptr<yg::OverlayElement> const GetClosestToPivot(list<shared_ptr<yg::Overl
bool Framework::GetVisiblePOI(m2::PointD const & pxPoint, m2::PointD & pxPivot, AddressInfo & info) const
{
if (!m_renderPolicy)
{
LOG(LINFO, ("GetVisiblePOI called without valid renderPolicy!"));
return false;
}
m2::PointD const pt = m_navigator.ShiftPoint(pxPoint);
double const halfSize = TOUCH_PIXEL_RADIUS * m_renderPolicy->VisualScale();
double const halfSize = TOUCH_PIXEL_RADIUS * GetVisualScale();
typedef yg::OverlayElement ElementT;

View file

@ -78,6 +78,11 @@ protected:
scoped_ptr<RenderPolicy> m_renderPolicy;
/// Safe function to get current visual scale.
/// Call it when you need do calculate pixel rect (not matter if m_renderPolicy == 0).
/// @return 1.0 if m_renderPolicy == 0 (possible for Android).
double GetVisualScale() const;
double m_StartForegroundTime;
/// @todo Need deep analyzing in future.
@ -180,8 +185,10 @@ public:
/// Get bookmark by touch.
/// @param[in] pixPt Coordinates of touch point in pixels.
/// @return NULL If there is no bookmark found
BookmarkAndCategory GetBookmark(m2::PointD pixPt) const;
BookmarkAndCategory GetBookmark(m2::PointD pixPt, double visualScale) const;
BookmarkAndCategory GetBookmark(m2::PointD const & pxPoint) const;
BookmarkAndCategory GetBookmark(m2::PointD const & pxPoint, double visualScale) const;
void ShowBookmark(Bookmark const & bm);
void ClearBookmarks();

View file

@ -153,7 +153,7 @@ UNIT_TEST(Bookmarks_ExportKML)
CheckBookmarks(*cat2);
FileWriter::DeleteFileX(BOOKMARKS_FILE_NAME);
cat2->SaveToKMLFileAtPath("./");
cat2->SaveToKMLFile();
delete cat2;
cat2 = BookmarkCategory::CreateFromKMLFile(BOOKMARKS_FILE_NAME);