ListUserConfigParam<T, U>::ListUserConfigParam(const char* param_name,
                                           const char* comment)
{
    m_param_name = param_name;
    all_params.push_back(this);
    if(comment != NULL) m_comment = comment;
}   // ListUserConfigParam
// ============================================================================
GroupUserConfigParam::GroupUserConfigParam(const char* group_name,
                                           const char* comment)
{
    m_param_name = group_name;
    all_params.push_back(this);
    if(comment != NULL) m_comment = comment;
}   // GroupUserConfigParam
int main(int argc, const char *argv[])
{
    PtrVector<Test> vec;  //vector<Test*>   
    for (int i = 0; i < 5; i++) {
        vec.push_back(new Test);
    }
    return 0;
}
/** Rebuild the list of tracks and GPs. This need to be recomputed e.g. to
 *  take unlocked tracks into account.
 */
void TracksScreen::buildTrackList()
{
    DynamicRibbonWidget* tracks_widget = this->getWidget<DynamicRibbonWidget>("tracks");
    RibbonWidget* tabs = this->getWidget<RibbonWidget>("trackgroups");

    // Reset track list everytime (accounts for locking changes, etc.)
    tracks_widget->clearItems();
    m_random_track_list.clear();

    const std::string& curr_group_name = tabs->getSelectionIDString(0);

    const int track_amount = (int)track_manager->getNumberOfTracks();

    // First build a list of all tracks to be displayed
    // (e.g. exclude arenas, ...)
    PtrVector<Track, REF> tracks;
    for (int n = 0; n < track_amount; n++)
    {
        Track* curr = track_manager->getTrack(n);
        if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_EASTER_EGG
            && !curr->hasEasterEggs())
            continue;
        if (curr->isArena() || curr->isSoccer()||curr->isInternal()) continue;
        if (curr_group_name != ALL_TRACK_GROUPS_ID &&
            !curr->isInGroup(curr_group_name)) continue;

        tracks.push_back(curr);
    }   // for n<track_amount

    tracks.insertionSort();
    for (unsigned int i = 0; i < tracks.size(); i++)
    {
        Track *curr = tracks.get(i);
        if (PlayerManager::getCurrentPlayer()->isLocked(curr->getIdent()))
        {
            tracks_widget->addItem(
                _("Locked : solve active challenges to gain access to more!"),
                "locked", curr->getScreenshotFile(), LOCKED_BADGE,
                IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
        }
        else
        {
            tracks_widget->addItem(translations->fribidize(curr->getName()),
                curr->getIdent(),
                curr->getScreenshotFile(), 0,
                IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
            m_random_track_list.push_back(curr->getIdent());
        }
    }

    tracks_widget->addItem(_("Random Track"), "random_track",
                           "/gui/track_random.png", 0 /* no badge */,
                           IconButtonWidget::ICON_PATH_TYPE_RELATIVE);

    tracks_widget->updateItemDisplay();
    std::random_shuffle( m_random_track_list.begin(), m_random_track_list.end() );
}   // buildTrackList
// ============================================================================
StringUserConfigParam::StringUserConfigParam(const char* default_value,
                                             const char* param_name,
                                             const char* comment)
{
    m_value         = default_value;
    m_default_value = default_value;
    m_param_name    = param_name;
    all_params.push_back(this);
    if(comment != NULL) m_comment = comment;
}   // StringUserConfigParam
// ============================================================================
TimeUserConfigParam::TimeUserConfigParam(StkTime::TimeType default_value,
                                         const char* param_name,
                                         const char* comment)
{
    m_value         = default_value;
    m_default_value = default_value;
    m_param_name    = param_name;
    all_params.push_back(this);
    if(comment != NULL) m_comment = comment;
}   // TimeUserConfigParam
ListUserConfigParam<T,U>::ListUserConfigParam(const char* param_name,
                                           const char* comment,
                                           int nb_elements,
                                           ...)
{
    m_param_name = param_name;
    all_params.push_back(this);
    if(comment != NULL) m_comment = comment;

    // add the default list
    va_list arguments;
    va_start ( arguments, nb_elements );
    for ( int i = 0; i < nb_elements; i++ )
        m_elements.push_back(T(va_arg ( arguments, U )));
    va_end ( arguments );                  // Cleans up the list
}   // ListUserConfigParam
Exemple #8
0
int main(int argc, char* argv[]) {
  google::InitGoogleLogging(argv[0]);
  gflags::ParseCommandLineFlags(&argc, &argv, true);

  // Detect the hardware concurrency level.
  const std::size_t num_hw_threads =
      DefaultsConfigurator::GetNumHardwareThreads();

  // Use the command-line value if that was supplied, else use the value
  // that we computed above, provided it did return a valid value.
  // TODO(jmp): May need to change this at some point to keep one thread
  //            available for the OS if the hardware concurrency level is high.
  const unsigned int real_num_workers = quickstep::FLAGS_num_workers != 0
                                      ? quickstep::FLAGS_num_workers
                                      : (num_hw_threads != 0 ?
                                         num_hw_threads
                                         : 1);

  if (real_num_workers > 0) {
    printf("Starting Quickstep with %d worker thread(s) and a %.2f GB buffer pool\n",
           real_num_workers,
           (static_cast<double>(quickstep::FLAGS_buffer_pool_slots) * quickstep::kSlotSizeBytes)/quickstep::kAGigaByte);
  } else {
    LOG(FATAL) << "Quickstep needs at least one worker thread to run";
  }

#ifdef QUICKSTEP_HAVE_FILE_MANAGER_HDFS
  if (quickstep::FLAGS_use_hdfs) {
    LOG(INFO) << "Using HDFS as the default persistent storage, with namenode at "
              << quickstep::FLAGS_hdfs_namenode_host << ":"
              << quickstep::FLAGS_hdfs_namenode_port << " and block replication factor "
              << quickstep::FLAGS_hdfs_num_replications << "\n";
  }
#endif

  // Initialize the thread ID based map here before the Foreman and workers are
  // constructed because the initialization isn't thread safe.
  quickstep::ClientIDMap::Instance();

  MessageBusImpl bus;
  bus.Initialize();

  // The TMB client id for the main thread, used to kill workers at the end.
  const client_id main_thread_client_id = bus.Connect();
  bus.RegisterClientAsSender(main_thread_client_id, kPoisonMessage);

  // Setup the paths used by StorageManager.
  string fixed_storage_path(quickstep::FLAGS_storage_path);
  if (!fixed_storage_path.empty()
      && (fixed_storage_path.back() != quickstep::kPathSeparator)) {
    fixed_storage_path.push_back(quickstep::kPathSeparator);
  }

  string catalog_path(fixed_storage_path);
  catalog_path.append("catalog.pb.bin");
  if (quickstep::FLAGS_initialize_db) {  // Initialize the database
    // TODO(jmp): Refactor the code in this file!
    LOG(INFO) << "Initializing the database, creating a new catalog file and storage directory\n";

    // Create the directory
    // TODO(jmp): At some point, likely in C++-17, we will just have the
    //            filesystem path, and we can clean this up
#ifdef QUICKSTEP_OS_WINDOWS
    std::filesystem::create_directories(fixed_storage_path);
    LOG(FATAL) << "Failed when attempting to create the directory: " << fixed_storage_path << "\n";
    LOG(FATAL) << "Check if the directory already exists. If so, delete it or move it before initializing \n";
#else
    {
      string path_name = "mkdir " + fixed_storage_path;
      if (std::system(path_name.c_str())) {
        LOG(FATAL) << "Failed when attempting to create the directory: " << fixed_storage_path << "\n";
      }
    }
#endif

    // Create the default catalog file.
    std::ofstream catalog_file(catalog_path);
    if (!catalog_file.good()) {
      LOG(FATAL) << "ERROR: Unable to open catalog.pb.bin for writing.\n";
    }

    quickstep::Catalog catalog;
    catalog.addDatabase(new quickstep::CatalogDatabase(nullptr, "default"));

    if (!catalog.getProto().SerializeToOstream(&catalog_file)) {
      LOG(FATAL) << "ERROR: Unable to serialize catalog proto to file catalog.pb.bin\n";
      return 1;
    }

    // Close the catalog file - it will be reopened below by the QueryProcessor.
    catalog_file.close();
  }

  // Setup QueryProcessor, including CatalogDatabase and StorageManager.
  std::unique_ptr<QueryProcessor> query_processor;
  try {
    query_processor.reset(new QueryProcessor(catalog_path, fixed_storage_path));
  } catch (const std::exception &e) {
    LOG(FATAL) << "FATAL ERROR DURING STARTUP: "
               << e.what()
               << "\nIf you intended to create a new database, "
               << "please use the \"-initialize_db=true\" command line option.";
  } catch (...) {
    LOG(FATAL) << "NON-STANDARD EXCEPTION DURING STARTUP";
  }

  // Parse the CPU affinities for workers and the preloader thread, if enabled
  // to warm up the buffer pool.
  const vector<int> worker_cpu_affinities =
      InputParserUtil::ParseWorkerAffinities(real_num_workers,
                                             quickstep::FLAGS_worker_affinities);

  const std::size_t num_numa_nodes_covered =
      DefaultsConfigurator::GetNumNUMANodesCoveredByWorkers(worker_cpu_affinities);

  if (quickstep::FLAGS_preload_buffer_pool) {
    std::chrono::time_point<std::chrono::steady_clock> preload_start, preload_end;
    preload_start = std::chrono::steady_clock::now();
    printf("Preloading the buffer pool ... ");
    fflush(stdout);
    quickstep::PreloaderThread preloader(*query_processor->getDefaultDatabase(),
                                         query_processor->getStorageManager(),
                                         worker_cpu_affinities.front());

    preloader.start();
    preloader.join();
    preload_end = std::chrono::steady_clock::now();
    printf("in %g seconds\n",
           std::chrono::duration<double>(preload_end - preload_start).count());
  }

  Foreman foreman(&bus,
                  query_processor->getDefaultDatabase(),
                  query_processor->getStorageManager(),
                  num_numa_nodes_covered);

  // Get the NUMA affinities for workers.
  vector<int> cpu_numa_nodes = InputParserUtil::GetNUMANodesForCPUs();
  if (cpu_numa_nodes.empty()) {
    // libnuma is not present. Assign -1 as the NUMA node for every worker.
    cpu_numa_nodes.assign(worker_cpu_affinities.size(), -1);
  }

  vector<int> worker_numa_nodes;
  PtrVector<Worker> workers;
  vector<client_id> worker_client_ids;

  // Initialize the worker threads.
  DCHECK_EQ(static_cast<std::size_t>(real_num_workers),
            worker_cpu_affinities.size());
  for (std::size_t worker_thread_index = 0;
       worker_thread_index < worker_cpu_affinities.size();
       ++worker_thread_index) {
    int numa_node_id = -1;
    if (worker_cpu_affinities[worker_thread_index] >= 0) {
      // This worker can be NUMA affinitized.
      numa_node_id = cpu_numa_nodes[worker_cpu_affinities[worker_thread_index]];
    }
    worker_numa_nodes.push_back(numa_node_id);

    workers.push_back(
        new Worker(worker_thread_index, &bus, worker_cpu_affinities[worker_thread_index]));
    worker_client_ids.push_back(workers.back().getBusClientID());
  }

  // TODO(zuyu): Move WorkerDirectory within Shiftboss once the latter is added.
  WorkerDirectory worker_directory(worker_cpu_affinities.size(),
                                   worker_client_ids,
                                   worker_numa_nodes);

  foreman.setWorkerDirectory(&worker_directory);

  // Start the worker threads.
  for (Worker &worker : workers) {
    worker.start();
  }

  LineReaderImpl line_reader("quickstep> ",
                             "      ...> ");
  std::unique_ptr<SqlParserWrapper> parser_wrapper(new SqlParserWrapper());
  std::chrono::time_point<std::chrono::steady_clock> start, end;

  for (;;) {
    string *command_string = new string();
    *command_string = line_reader.getNextCommand();
    if (command_string->size() == 0) {
      delete command_string;
      break;
    }

    parser_wrapper->feedNextBuffer(command_string);

    bool quitting = false;
    // A parse error should reset the parser. This is because the thrown quickstep
    // SqlError does not do the proper reset work of the YYABORT macro.
    bool reset_parser = false;
    for (;;) {
      ParseResult result = parser_wrapper->getNextStatement();
      if (result.condition == ParseResult::kSuccess) {
        if (result.parsed_statement->getStatementType() == ParseStatement::kQuit) {
          quitting = true;
          break;
        }

        if (result.parsed_statement->getStatementType() == ParseStatement::kCommand) {
          try {
            quickstep::cli::executeCommand(
                *result.parsed_statement,
                *(query_processor->getDefaultDatabase()), stdout);
          } catch (const quickstep::SqlError &sql_error) {
            fprintf(stderr, "%s",
                    sql_error.formatMessage(*command_string).c_str());
            reset_parser = true;
            break;
          }
        continue;
        }

        std::unique_ptr<QueryHandle> query_handle;
        try {
          query_handle.reset(query_processor->generateQueryHandle(*result.parsed_statement));
        } catch (const quickstep::SqlError &sql_error) {
          fprintf(stderr, "%s", sql_error.formatMessage(*command_string).c_str());
          reset_parser = true;
          break;
        }

        DCHECK(query_handle->getQueryPlanMutable() != nullptr);
        foreman.setQueryPlan(query_handle->getQueryPlanMutable()->getQueryPlanDAGMutable());

        foreman.reconstructQueryContextFromProto(query_handle->getQueryContextProto());

        try {
          start = std::chrono::steady_clock::now();
          foreman.start();
          foreman.join();
          end = std::chrono::steady_clock::now();

          const CatalogRelation *query_result_relation = query_handle->getQueryResultRelation();
          if (query_result_relation) {
            PrintToScreen::PrintRelation(*query_result_relation,
                                         query_processor->getStorageManager(),
                                         stdout);

            DropRelation::Drop(*query_result_relation,
                               query_processor->getDefaultDatabase(),
                               query_processor->getStorageManager());
          }

          query_processor->saveCatalog();
          printf("Execution time: %g seconds\n",
                 std::chrono::duration<double>(end - start).count());
        } catch (const std::exception &e) {
          fprintf(stderr, "QUERY EXECUTION ERROR: %s\n", e.what());
          break;
        }
        printf("Query Complete\n");
      } else {
        if (result.condition == ParseResult::kError) {
          fprintf(stderr, "%s", result.error_message.c_str());
        }
        reset_parser = true;
        break;
      }
    }

    if (quitting) {
      break;
    } else if (reset_parser) {
      parser_wrapper.reset(new SqlParserWrapper());
      reset_parser = false;
    }
  }

  // Terminate all workers before exiting.
  // The main thread broadcasts poison message to the workers. Each worker dies
  // after receiving poison message. The order of workers' death is irrelavant.
  MessageStyle style;
  style.Broadcast(true);
  Address address;
  address.All(true);
  std::unique_ptr<WorkerMessage> poison_message(WorkerMessage::PoisonMessage());
  TaggedMessage poison_tagged_message(poison_message.get(),
                                      sizeof(*poison_message),
                                      kPoisonMessage);

  const tmb::MessageBus::SendStatus send_status =
      bus.Send(main_thread_client_id,
               address,
               style,
               std::move(poison_tagged_message));
  CHECK(send_status == tmb::MessageBus::SendStatus::kOK) <<
     "Broadcast message from Foreman to workers failed";

  for (Worker &worker : workers) {
    worker.join();
  }

  return 0;
}
 void addListener(GUIEngine::ITextBoxWidgetListener* listener)
 {
     m_listeners.push_back(listener);
 }
Exemple #10
0
void KartSelectionScreen::setKartsFromCurrentGroup()
{
    RibbonWidget* tabs = getWidget<RibbonWidget>("kartgroups");
    assert(tabs != NULL);

    std::string selected_kart_group =
        tabs->getSelectionIDString(PLAYER_ID_GAME_MASTER);

    UserConfigParams::m_last_used_kart_group = selected_kart_group;

    // This can happen if addons are removed so that also the previously
    // selected kart group is removed. In this case, select the
    // 'standard' group
    if (selected_kart_group != ALL_KART_GROUPS_ID &&
        !kart_properties_manager->getKartsInGroup(selected_kart_group).size())
    {
        selected_kart_group = DEFAULT_GROUP_NAME;
    }

    DynamicRibbonWidget* w = getWidget<DynamicRibbonWidget>("karts");
    w->clearItems();

    int usable_kart_count = 0;
    PtrVector<const KartProperties, REF> karts;

    for(unsigned int i=0; i<kart_properties_manager->getNumberOfKarts(); i++)
    {
        const KartProperties* prop = kart_properties_manager->getKartById(i);
        // Ignore karts that are not in the selected group
        if(selected_kart_group != ALL_KART_GROUPS_ID &&
            !prop->isInGroup(selected_kart_group))
            continue;
        karts.push_back(prop);
    }
    karts.insertionSort();

    for(unsigned int i=0; i<karts.size(); i++)
    {
        const KartProperties* prop = karts.get(i);
        if (PlayerManager::getCurrentPlayer()->isLocked(prop->getIdent()) &&
            !m_multiplayer)
        {
            w->addItem(_("Locked : solve active challenges to gain access to more!"),
                       ID_LOCKED + prop->getIdent(),
                       prop->getAbsoluteIconFile(), LOCKED_BADGE,
                       IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
        }
        else
        {
            w->addItem(translations->fribidize(prop->getName()),
                       prop->getIdent(),
                       prop->getAbsoluteIconFile(), 0,
                       IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
            usable_kart_count++;
        }
    }

    // add random
    if (usable_kart_count > 1)
    {
        w->addItem(_("Random Kart"), RANDOM_KART_ID, "/gui/random_kart.png");
    }

    w->updateItemDisplay();
}
 void manualInsertObject(TrackObject* obj)
 {
     m_all_objects.push_back(obj);
 }
void Screen::parseScreenFileDiv(irr::io::IXMLReader* xml, PtrVector<Widget>& append_to,
                                irr::gui::IGUIElement* parent)
{
    // parse XML file
    while (xml && xml->read())
    {
        
        switch (xml->getNodeType())
        {
            case irr::io::EXN_TEXT:
            {
                break;
            }
            
            case irr::io::EXN_ELEMENT:
            {
                /* find which type of widget is specified by the current tag, and instanciate it */
                if (wcscmp(L"div", xml->getNodeName()) == 0)
                {
                    Widget* w = new Widget(WTYPE_DIV);
                    append_to.push_back(w);
                }
                else if (wcscmp(L"stkgui", xml->getNodeName()) == 0)
                {
                    // outer node that's there only to comply with XML standard (and expat)
                    continue;
                }
                else if (wcscmp(L"placeholder", xml->getNodeName()) == 0)
                {
                    Widget* w = new Widget(WTYPE_DIV, true);
                    append_to.push_back(w);
                }
                else if (wcscmp(L"box", xml->getNodeName()) == 0)
                {
                    Widget* w = new Widget(WTYPE_DIV);
                    w->m_show_bounding_box = true;
                    append_to.push_back(w);
                }
                else if (wcscmp(L"bottombar", xml->getNodeName()) == 0)
                {
                    Widget* w = new Widget(WTYPE_DIV);
                    w->m_bottom_bar = true;
                    append_to.push_back(w);
                }
                else if (wcscmp(L"topbar", xml->getNodeName()) == 0)
                {
                    Widget* w = new Widget(WTYPE_DIV);
                    w->m_top_bar = true;
                    append_to.push_back(w);
                }
                else if (wcscmp(L"roundedbox", xml->getNodeName()) == 0)
                {
                    Widget* w = new Widget(WTYPE_DIV);
                    w->m_show_bounding_box = true;
                    w->m_is_bounding_box_round = true;
                    append_to.push_back(w);
                }
                else if (wcscmp(L"ribbon", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new RibbonWidget());
                }
                else if (wcscmp(L"buttonbar", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new RibbonWidget(RIBBON_TOOLBAR));
                }
                else if (wcscmp(L"tabs", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new RibbonWidget(RIBBON_TABS));
                }
                else if (wcscmp(L"spinner", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new SpinnerWidget());
                }
                else if (wcscmp(L"button", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new ButtonWidget());
                }
                else if (wcscmp(L"gauge", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new SpinnerWidget(true));
                }
                else if (wcscmp(L"progressbar", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new ProgressBarWidget());
                }
                else if (wcscmp(L"icon-button", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new IconButtonWidget());
                }
                else if (wcscmp(L"icon", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new IconButtonWidget(IconButtonWidget::SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO,
                                                             false, false));
                }
                else if (wcscmp(L"checkbox", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new CheckBoxWidget());
                }
                else if (wcscmp(L"label", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new LabelWidget());
                }
                else if (wcscmp(L"bright", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new LabelWidget(false, true));
                }
                else if (wcscmp(L"bubble", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new BubbleWidget());
                }
                else if (wcscmp(L"header", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new LabelWidget(true));
                }
                else if (wcscmp(L"spacer", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new Widget(WTYPE_SPACER));
                }
                else if (wcscmp(L"ribbon_grid", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new DynamicRibbonWidget(false /* combo */, true /* multi-row */));
                }
                else if (wcscmp(L"scrollable_ribbon", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new DynamicRibbonWidget(true /* combo */, false /* multi-row */));
                }
                else if (wcscmp(L"scrollable_toolbar", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new DynamicRibbonWidget(false /* combo */, false /* multi-row */));
                }
                else if (wcscmp(L"model", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new ModelViewWidget());
                }
                else if (wcscmp(L"list", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new ListWidget());
                }
                else if (wcscmp(L"textbox", xml->getNodeName()) == 0)
                {
                    append_to.push_back(new TextBoxWidget());
                }
                else
                {
                    std::cerr << "/!\\ Warning /!\\ : unknown tag found in STK GUI file  : '"
                              << xml->getNodeName()  << "'" << std::endl;
                    continue;
                }
                
                /* retrieve the created widget */
                Widget& widget = append_to[append_to.size()-1];
                
                /* read widget properties using macro magic */
                
#define READ_PROPERTY( prop_name, prop_flag ) const wchar_t* prop_name = xml->getAttributeValue( L###prop_name ); \
if(prop_name != NULL) widget.m_properties[prop_flag] = core::stringc(prop_name).c_str(); else widget.m_properties[prop_flag] = ""
                
                READ_PROPERTY(id,             PROP_ID);
                READ_PROPERTY(proportion,     PROP_PROPORTION);
                READ_PROPERTY(width,          PROP_WIDTH);
                READ_PROPERTY(height,         PROP_HEIGHT);
                READ_PROPERTY(child_width,    PROP_CHILD_WIDTH);
                READ_PROPERTY(child_height,   PROP_CHILD_HEIGHT);
                READ_PROPERTY(word_wrap,      PROP_WORD_WRAP);
                //READ_PROPERTY(grow_with_text, PROP_GROW_WITH_TEXT);
                READ_PROPERTY(x,              PROP_X);
                READ_PROPERTY(y,              PROP_Y);
                READ_PROPERTY(layout,         PROP_LAYOUT);
                READ_PROPERTY(align,          PROP_ALIGN);
                
                READ_PROPERTY(icon,           PROP_ICON);
                READ_PROPERTY(focus_icon,     PROP_FOCUS_ICON);
                READ_PROPERTY(text_align,     PROP_TEXT_ALIGN);
                READ_PROPERTY(min_value,      PROP_MIN_VALUE);
                READ_PROPERTY(max_value,      PROP_MAX_VALUE);
                READ_PROPERTY(square_items,   PROP_SQUARE);
                
                READ_PROPERTY(max_width,      PROP_MAX_WIDTH);
                READ_PROPERTY(max_height,     PROP_MAX_HEIGHT);
                READ_PROPERTY(extend_label,   PROP_EXTEND_LABEL);
                READ_PROPERTY(label_location, PROP_LABELS_LOCATION);
                READ_PROPERTY(max_rows,       PROP_MAX_ROWS);
                READ_PROPERTY(wrap_around,    PROP_WRAP_AROUND);
#undef READ_PROPERTY
                
                const wchar_t* text = xml->getAttributeValue( L"text" );
                
                if (text != NULL)
                {
                    widget.m_text = _(text);
                    widget.m_is_text_rtl = (translations->isRTLLanguage() && widget.m_text != text);
                }
                
                if (parent != NULL)
                {
                    widget.setParent(parent);
                }
                
                /* a new div starts here, continue parsing with this new div as new parent */
                if (widget.getType() == WTYPE_DIV || widget.getType() == WTYPE_RIBBON)
                {
                    parseScreenFileDiv( xml, append_to[append_to.size()-1].m_children, parent );
                }
            }// end case EXN_ELEMENT
                
                break;
            case irr::io::EXN_ELEMENT_END:
            {
                // we're done parsing this 'div', return one step back in the recursive call
                if (wcscmp(L"div", xml->getNodeName()) == 0)
                    return;
                if (wcscmp(L"box", xml->getNodeName()) == 0)
                    return;
                if (wcscmp(L"placeholder", xml->getNodeName()) == 0)
                    return;
                if (wcscmp(L"roundedbox", xml->getNodeName()) == 0)
                    return;
                if (wcscmp(L"bottombar", xml->getNodeName()) == 0)
                    return;
                if (wcscmp(L"topbar", xml->getNodeName()) == 0)
                    return;
                
                // We're done parsing this 'ribbon', return one step back in
                // the recursive call.
                if (wcscmp(L"ribbon", xml->getNodeName()) == 0 ||
                    wcscmp(L"buttonbar", xml->getNodeName()) == 0 ||
                    wcscmp(L"tabs", xml->getNodeName()) == 0)
                    return;
            }
                break;
                
            default: break;
        }//end switch
    } // end while
} // end function