Cartographic features of Samsung Bada

    Preliminary notes


    Hello. We will talk about how to create a simple application for the Samsung Bada mobile platform that allows you to display a map on the smartphone screen, perform manipulations with it and solve simple problems. The beginning of development for Bada is described by me here .



    Preliminary Actions


    The map data provider for smartphones with Bada is not ... Google. (For me, after the Android world, this was a bit of a shock, and I felt some discomfort and immediately thought - how easily we get used to the little things and how powerful virtual things are (I remembered the topic on Habré about the indignation of users that Google removed the link of its reader from the main page ). However, I was distracted ...

    The article is structured this way. First, the general task of showing a card with a minimum of functionality is solved to give an idea of ​​the logic of the SDK developers themselves, and only then a small but useful feature will be added. This approach is caused by the fact that I spent many hours before, among the wilds of the cunningly wise C ++, in the examples and documentation, to isolate actually a number of those actions that need to be taken for an “initial acquaintance”, and only then move on.

    So, before programming, we need to perform a number of additional steps. First of all, register on the website of the map data provider for Samsung Bada deCarta(the link does not point to the main page, but immediately to DevZone). The site, I must say, is unusual - when I logged in with Chrome, I found that the password is entered into the form without the usual asterisks, and the reaction to the registration purpose - getting the username and password for working with their cards - I have to be puzzled by email without any hint on this. In general, after registration (it is possible to directly indicate that you intend to work specifically for Bada), it took me about 10 minutes, after which I received a letter stating the username and password, which we will use in the future.

    Application Prerequisites


    Having created a form-based project using the BADA IDE, I immediately deleted the button that was kindly added to the form and its initialization code, which is located in the form class method
    result
    SimpleMapForm::OnInitializing(void)
    (I named the form SimpleMapForm), since the map will occupy the form and the button, in fact, to anything. Nevertheless, in order to have controls for the application, after clicking on the form, I opened the Properties tab and indicated that I want to see two “Soft Key” keys with the inscriptions Zoom In and Zoom Out on the form, changing the properties of Show Softkey0, respectively. SoftKey0 Text, Show Softkey1, Softkey1 Text. What happened looks like this (the inscription is not completely visible, but this problem does not exist in the running application):



    One of the typical tasks when working with a map on mobile devices is its scaling, panning, etc. In order to be able to track the user's touch on the screen and interpret them in the map, for the form class I added a link to the “listener” (I don’t like English word tracing, so forgive me for such homegrown terminology) of these actions
     public Osp::Locations::Controls::IMapEventListener 
    in the form header file. "Listener" declared in the header file, which by default does not exist and you must remember to add it. In general, this part of the code is as follows:

    
    #include 
    #include 
    #include 
    #include 
    #include 
    class SimpleMapForm :
    	public Osp::Ui::Controls::Form,
    	public Osp::Locations::Controls::IMapEventListener,
    	public Osp::Ui::IActionEventListener
    {
    // Construction
    public:
    	SimpleMapForm(void);
    	virtual ~SimpleMapForm(void);
    


    For the added “listener”, it is necessary to determine the handlers of those events that can be called in response to various user manipulations with the card. For now, we will not implement them, but simply add them to the public section of the form class:

    
    	//обработчики карты
    	void OnMapMovingStarted(const Osp::Locations::Controls::Map& source){}
    	void OnMapMovingEnded(const Osp::Locations::Controls::Map& source){}
    	void OnMapZoomingStarted(const Osp::Locations::Controls::Map& source, const bool zoomIn){}
    	void OnMapZoomingEnded(const Osp::Locations::Controls::Map& source, const bool zoomIn){}
    	void OnMapDrawCompleted(const Osp::Locations::Controls::Map& source){}
    	//обработчики информационных окошек
    	void OnClosingEnded(const Osp::Locations::Controls::IMapInfoWindow& source){}
    	void OnInfoWindowClicked(const Osp::Locations::Controls::IMapInfoWindow& source){}
    	void OnMapClicked(const Osp::Locations::Controls::Map& source,
    					  const Osp::Graphics::Point& point, const Osp::Locations::Coordinates& coordinates){}
    void OnInfoWindowDoublePressed(const Osp::Locations::Controls::IMapInfoWindow& source){}
    


    As such, there is no Map GUI component in the IDE, so you will have to add it “in code”.

    We’ll declare the card provider and the card itself in the application. To do this, let’s go back to the header file of the form class and in the private section (this is what developers recommend, but I didn’t find a clear explanation for what such a detailed specification is, honestly) we add an announcement:

    
     protected:
    private:
    	Osp::Locations::Services::IMapServiceProvider*	__pMapSvcProvider;
    	Osp::Locations::Controls::Map*				__pMap;
    


    Now in the cpp file of the form class we add namespaces:

    
    using namespace Osp::Locations;
    using namespace Osp::Graphics;
    using namespace Osp::Locations::Services;
    using namespace Osp::Locations::Controls;
    


    and initialization of the card provider and the card itself in the form class constructor

    
    SimpleMapForm::SimpleMapForm(void):
    		__pMapSvcProvider(null),
    		__pMap(null)
    {
    }
    


    Now here you can now find a form initialization method
    result SimpleMapForm::OnInitializing(void)
    and add the provider and map creation to it:

    
    const String providerName = L"deCarta";
    	const String extraInfo = L"ClientName=***;ClientPassword=***;HostUrl=http://developer.kr.dz.decarta.com:80/openls/openls";
    	const String prefProperty = L"global-mobile";
    	Coordinates center;
    	Rectangle clientRect = GetClientAreaBounds();
    	__pMapSvcProvider = static_cast(ProviderManager::ConnectToServiceProviderN(providerName, LOC_SVC_PROVIDER_TYPE_MAP, extraInfo));
    	__pMap = new Map();
    	__pMap->Construct(Rectangle(0,0, clientRect.width, clientRect.height), *__pMapSvcProvider);
    	 center.Set(48,37.8, 200);
    	__pMap->SetCenter(center, false);
    	__pMap->SetZoomLevel(12.0, false);
    	__pMap->AddMapEventListener(*this);
    	AddControl(*__pMap);
    


    Constants with fairly transparent names are declared in the code, the only thing that follows is that in extraInfo, in the line in the sections ClientName and ClientPassword, you must specify the login and password you received from deCarta, respectively.

    Next, in clientRect, we return the dimensions of the client area of ​​the form (that is, without a header), create a map provider and the card itself, setting its dimensions to the same dimensions of the form. (I almost forgot, for Rectangle you need to add the Osp :: Graphics space). Then, setting the latitude, longitude and height of the center of the map, we pass it to the SetCenter method. I set its second parameter, which is responsible for the animation effects when working with the card, to false, because even without any animation, the speed of the smartphone simulator is, to put it mildly, “not a fountain”. Then in SetZoomLevel we set the desired map scale (the second parameter here is also responsible for the animation), quickly add “listeners” to the map and add it to the form.

    At this stage, you can already build the project, launch it and see how it looks in Bada.

    My simulator with the application running looks like this:



    In principle, pretty nice and pretty detailed for a mobile map (we used the const "global-mobile" level of detail). Although, of course, the question of comparing this with maps from Google or Yandex remains open, and it seems that this will be the topic of the next topic.

    Although this application already has some functionality - you can drag and drop the card, say, it has no special meaning and it needs some usefulness.

    Let's allow the user to scale the map - for this we added two Soft keys to the application (it is difficult to find the corresponding Russian term).

    To do this, both keys should be assigned an identifier for the event, which will be transmitted to the handler and "listener" of this event. Let's do this programmatically in the method code
    SimpleMapForm::OnInitializing(void)
    class form. Add the following to it:

    
    result
    SimpleMapForm::OnInitializing(void)
    {
    	result r = E_SUCCESS;
        SetSoftkeyActionId(SOFTKEY_0,ID_ZOOM_IN);
        AddSoftkeyActionListener(SOFTKEY_0,*this);
        SetSoftkeyActionId(SOFTKEY_1,ID_ZOOM_OUT);
        AddSoftkeyActionListener(SOFTKEY_1,*this);
        SetOptionkeyActionId(ID_OPTION_MENU);
        AddOptionkeyActionListener(*this);
    


    First you need to go back to the header file of the form class and add two constants ID_ZOOM_IN and ID_ZOOM_OUT to it that will identify the touch events on the buttons.

    
    protected:
      // идентификаторы действий для кнопок масштабирования
      static const int ID_ZOOM_IN = 701;
      static const int ID_ZOOM_OUT = 702;
    


    With this, we can already handle clicking on the Zoom In and Zoom Out buttons. To do this, find the method in the cpp file of the form class
    SimpleMapForm::OnActionPerformed(constOsp::Ui::Control& source, int actionId)
    

    which is designed to handle all the events that occur in the application by analyzing the actionId parameter.
    Add the following code to it:

    
    switch (actionId) {
    		case ID_ZOOM_IN:
    			{
    		// увеличение масштаба карты
    						float curZoomLevel = __pMap->GetZoomLevel();
    						if (curZoomLevel == __pMap->GetMaxZoomLevel())
    						{
    							return;
    						}
    						++curZoomLevel;
    						if (curZoomLevel > __pMap->GetMaxZoomLevel())
    						{
    							curZoomLevel = __pMap->GetMaxZoomLevel();
    						}
    						__pMap->SetZoomLevel(curZoomLevel, true);
    						RequestRedraw(true);
                   // -----------------------------
    		}
    			break;
    		case ID_ZOOM_OUT:{
    	// уменьшение масштаба карты
    			            float curZoomLevel = __pMap->GetZoomLevel();
    						if (curZoomLevel == 1.0)
    						{
    							return;
    						}
    						--curZoomLevel;
    						if (curZoomLevel < 1.0)
    						{
    							curZoomLevel = 1.0;
    						}
    						__pMap->SetZoomLevel(curZoomLevel, true);
    						RequestRedraw(true);
    	    //-----------------------------
    		}
    		break;
    default:
    			break;
    	}
    


    The meaning is as follows - the user presses a button, for example, Zoom In; this is followed by the assigned “listener” and the constant ID_ZOOM_IN that we assigned to this event is passed to OnActionPerformed, where we analyze the actionId; then actionId will have the value ID_ZOOM_IN and the corresponding case block will be executed. The code itself, I think, is understandable and hardly requires explanation, since the names of the methods have transparent names. The only moment - after changing the scale of SetZoomLevel, we ask the form to “redraw” :)

    It looks like this on the simulator:

    1. The original scale immediately after launch:

    2. After Zoom In:

    3. And almost the maximum Zoom:


    Looking at the last snapshot of the simulator, you can easily notice that there are simply no house numbers (for the first time I sat in the hope that they would load), unlike Google Maps or Yandex Maps, and this street is almost the center of Donetsk, although banks and even ATMs carefully noted.

    And now it's almost the final - let’s give the user the opportunity to see a certain place on the map by certain coordinates.

    Bada has Popup pop-ups very similar to MessageBox (you can see the last one in my first article), but you can place controls on them, which seems pretty convenient - you don’t need to create an entire form for a couple of input fields and a button. We will take advantage of this.

    Create a Popup by going to the IDE in the Resources resource box and on the node of the Popups tree. Right-click and select Open Insert Wizard. For the desired screen resolution, select Popup and click Finish - something like IDP_Popup1 will appear in Resources. Left-click on “this” and see how the visual interface builder opens, onto which you can drag and drop controls onto the form. I created the following Popup:



    Now let's add the ability to click on something so that this Popup appears. Let's go back to the form and add the optional menu to the form by setting the Show OptionKey property to True. We get something like this on the form:



    For OptionKey, add the event identifier and its “listener” in the method
    SimpleMapForm::OnInitializing(void)
    right after a similar code for Zoom In and ZoomOut, create it and add one “Change place” item:

    
    SetOptionkeyActionId(ID_OPTION_MENU);
    AddOptionkeyActionListener(*this);
        // создание опционального меню
         __pOptionMenu = new OptionMenu();
         __pOptionMenu->Construct();
         __pOptionMenu->AddActionEventListener(*this);
         __pOptionMenu->AddItem(L"Change place",ID_OPTION_MENU_ACTION1);
    


    Please note that SetOptionkeyActionId (ID_OPTION_MENU) is the setting of the identifier for SHOWING OptionKey, and __pOptionMenu-> AddActionEventListener (* this) and __pOptionMenu-> AddItem (L "Change place", ID_OPTION_MENU_ACTION1) sets the listener ID to the listener and OptionKey. Of course, ID_OPTION_MENU and ID_OPTION_MENU_ACTION1 must be added to the header file of the form class.

    Let's create a Popup a little lower and do the typical actions with it:

     
            __pPopup = new Popup();
    	__pPopup->Construct(L"IDP_POPUP_SET_NEW_PLACE");
    	__pPopup->SetName(L"CommonPopup");
    	__popupX = static_cast(__pPopup->GetControl(L"IDC_EDITFIELD1"));
    	__popupY = static_cast(__pPopup->GetControl(L"IDC_EDITFIELD2"));
            __popupButtonOK = static_cast


    At the same time, I added declarations of all identifiers used to the private section of the form class - it now looks like this:

    
    private:
    	Osp::Locations::Services::IMapServiceProvider*	 __pMapSvcProvider;
    	Osp::Locations::Controls::Map*		         __pMap;
    	Osp::Ui::Controls::OptionMenu*                   __pOptionMenu;
    	Osp::Ui::Controls::Popup*                        __pPopup;
    // идентификаторы элементов управления на Popup
    	Osp::Ui::Controls::Label*      __popupLabelTitle;
    	Osp::Ui::Controls::Label*      __popupLabelX;
    	Osp::Ui::Controls::Label*      __popupLabelY;
    	Osp::Ui::Controls::EditField*  __popupX;
    	Osp::Ui::Controls::EditField*  __popupY;
    	Osp::Ui::Controls::Button*     __popupButtonOK;
    


    Here ... Now, we will process the Popup display in ActionPerformed and the reaction to closing it - accordingly, we will analyze the actionID for the values ​​ID_OPTION_MENU, ID_OPTION_MENU_ACTION1 and BUTTON_OK_POPUP.

    I did it like this:

    
    case ID_OPTION_MENU:{
    	// вызов опционального меню
                  __pOptionMenu->SetShowState(true);
                  __pOptionMenu->Show();
                  RequestRedraw(true);
           //-------------------------
    		}
    		break;
    		case ID_OPTION_MENU_ACTION1:{
         // обработка пункта 1 опциональго меню - показ Popup
                __pPopup->SetShowState(true);
                __pPopup->Show();
               RequestRedraw(true);
         // ---------------------
    		}
    		break;
    		case BUTTON_OK_POPUP:{
        // смена текущих координат центра карты
    			Coordinates newCenter;
    			String newXStr(__popupX->GetText());
    			String newYStr(__popupY->GetText());
    			double newX;
    			double newY;
    			result r1=Double::Parse(newXStr,newX);
    			result r2=Double::Parse(newYStr,newY);
    			newCenter.Set(newX, newY, 200);
    			__pMap->SetCenter(newCenter, false);
    			__pPopup->SetShowState(false);
                            __pPopup->Show();
                           RequestRedraw(true);
      //------------------
    		}
    


    Something with indentation :(

    Here, in the end we get the following:

    1. Click on OptionKey:

    2. Click on the OptionKey button, Popup appears and enter coordinates into it (you can ignore the text background, this is corrected by choosing the background color):

    3. And the final - a simulator view with a map loaded by new coordinates:


    conclusions

    Programming for Bada is difficult - my subjective opinion is after the world of Android and WP7 (my task is more global than the one I described above). The speed of the simulator is not a fountain. Documentation - rather to demonstrate the capabilities, for real work you have to delve into the examples. The lion's share of the developer forum is in Korean, although, frankly, they answered me quickly in the English language branch. But ... it works !!! Moreover, it works quite stably with cards, with SQLite, and even with the fact that I studied C ++ myself :)))

    Good luck in programming for Bada!
    Due to my modest abilities, I will try to answer questions if such arise.
    Thank you very much for your attention.

    Also popular now: