Skip to content
This repository was archived by the owner on Jan 16, 2021. It is now read-only.

Latest commit

 

History

History
771 lines (571 loc) · 19.4 KB

File metadata and controls

771 lines (571 loc) · 19.4 KB

| Home | Downloads | Examples | Documentation | Sources | Project | Contact | Gammasoft |

Folders and files organization

Folders hierarchy

√ DO Respect the project hierarchy

root
  +- build
  +- docs
  |    +- diagrams
  |    |    +- uml
  |    +- pictures
  |    +- tutorials
  |    +- movies
  +- examples
  |    +- appplication
  |    +- common_dialogs
  |    +- components
  |    +- ...
  +- scripts
  |    +- cmake
  |    +- install
  |    ±- ...
  ±- src
  |    +- xtd_forms
  |    |    +- include
  |    |    |    +- xtd
  |    |    |         +- forms
  |    |    |         |    +- layout
  |    |    |         |    +- ...
  |    |    |         ±- ...
  |    |    +- src
  |    |         +- xtd
  |    |              +- forms
  |    |              |    +- layout
  |    |              |    +- ...
  |    |              ±- ...
  |    +- ...
  +- tests
       +- xtd_forma_manual_tests
       +- xtd_forma_unit_tests
       |    +- xtd
       |         +- forms
       |         |    +- ...
       |         +- ...
       +- ...

root folder is the project folder where xtd.forms project was extracted or cloned.

root/build folder contains the build result. This folder is automaticaly create by the install.

root/docs folder contains markdown documentations.

root/docs/diagrams folder contains the diagrams used to illustrate the markdown documentation and website.

root/docs/diagrams/uml folder contains the UML diagrams used to illustrate the markdown documentation and website.

root/docs/pictures folder contains the pictures used to illustrate the markdown documentation and website.

root/docs/tutorials folder contains the xtd.forms tutorials.

root/docs/movies folder contains the movies used to demonstrate how to use xtd.forms.

root/examples folder contains examples to show how to used xtd.forms libraries.

root/scripts/cmake folder contains scripts needed by cmake.

root/scripts/install folder contains installation scripts.

root/src folder contains source files organized by libraries.

For each library the hierarchy is identical :

root/xtd_library_name/include folder contains include files for xtd_library_name library.

root/xtd_library_name/include/namespace1/namespace2/... folder contains include files for xtd_library_name library organized by namespaces.

root/xtd_library_name/src folder contains source files for xtd_library_name library.

root/xtd_library_name/src/namespace1/namespace2/... folder contains source files for xtd_library_name library organized by namespaces.

root/tests folder contains tests organized by library and test types.

For example, the root/src/xtd_forms folder contains xtd.forms library source files and the root/src/xtd_forms_native_win32 folder contains xtd.forms.native.win32 library source files.

For exemple, the root/tests/xtd_forms_unit_tests contains xtd_forms library unit tests.

For example, if a xtd.forms library header file contains :

#pragma once

#include <xtd/event_args.hpp>
#include "close_reason.hpp"

namespace xtd {
  namespace forms {
    class form_closed_event_args : public event_args {
    public:
      form_closed_event_args() = default;
      form_closed_event_args(forms::close_reason close_reason) : close_reason_(close_reason) {};

      /// @cond
      form_closed_event_args(const form_closed_event_args& form_closed_event_args) = default;
      form_closed_event_args& operator=(const form_closed_event_args& form_closed_event_args) = default;
      /// @endcond

      forms::close_reason close_reason() const {return this->close_reason_;}

    private:
      forms::close_reason close_reason_ = forms::close_reason::none;
    };
  }
}

The file will be in root/src/xtd.forms/include/xtd/forms/ path

File names

√ DO Name file with same name of the class, struct, enum, delegate or event that contains.

For example, if file contains :

#pragma once

#include <xtd/event_handler.hpp>
#include "form_closed_event_args.hpp"

namespace xtd {
  namespace forms {
    template<typename type_t>
    using form_closed_event_handler = delegate<void(const type_t& sender, const form_closed_event_args& e)>;
  }
}

The file will be named to form_closing_event_handler.hpp.

File extensions

√ DO Use .hpp for header files.

√ DO Use .cpp for source files.

Diagrams

√ DO Diagrams are generate by Draw.IO Desktop. Draw.IO Desktop is a Google Chrome extension.

UML diagrams

√ DO UML diuagrams are generate by plantUML.

Editor

√ DO Replace tab character with double spaces in your editor or IDE properties.

√ DO Use two space for indentation.

class my_control : public xtd::form::control {
public:
  my_control() = default;
  my_control(const my_control&) = default;
};

Order of parts in a class or struct declarations

First order is on protection type :

√ DO Put public members in first.

√ DO Put protected members in second.

√ DO And finaly put private members at least.

Second order for each protection type :

√ DO Put inner classes and structs in first.

√ DO Put constructors / Destructor / Copy operator in seconds.

√ DO Put properties in third.

√ DO Put events in fourth.

√ DO Put methods in fifth.

√ DO And put members in last.

√ DO Organize properties, events, methods and member in alphabetic order.

class my_control : public xtd::form::control {
public:
  my_control() = default;
  my_control(const my_control&) = defuult;
  my_control& my_control& operator=(const my_control& my_control);
  
  const std::string base_name() const {return this->base_name_;;}  
  intptr_t handle() const {return this->handle_;}
  
  xtd::event<my_control, event_handler<xtd::forms::control>> name_changed;
  
  std::string to_string() const override {return this->name_generator();}

protected:
  virtual std::string name_generator() const {return this->base_name_;}

  intptr_t handle_ = 0;
  
private:
  my_control(intptr_t handle);

  std::string base_name_ = "BaseName";
};

#define

X DO NOT Use #define for any good or bad reason.

√ DO But instead use static constexpr or static const for constantes.

header file :

class my_class {
public:
  static constexpr int max_value = std::numeric_limits<int>::max();
  static const xtd::min_version;
};

source file :

const xtd::version my_class::min_version(2, 1, 0);

√ Do All macro can be replaced by template method.

class math {
pubmic:
math() = delete;
  // equivalent : #define max(value1, value2) (value1 >= value2 ? value1 : value2)
  template<typename T>
  static T max(T value1, T value2) {return value1 >= value2 ? value1 : value2;}
};

Globals

Global methods

X DO NOT Use global methods. All methods are in class. If necessary creates container class like xtd::forms:cursors to group static methods.

global variables

X DO NOT Use global variables. All variables are in class. If necessary a global or static variable can create in a source files (.cpp) but it can't visible in the header file (.hpp).

√ DO Uses factory_method, builder or singleton patterns to create unique object.

Comments

√ DO Using always simple line comment // instead block comment /* */

// This is my
// multiline comment
int x = 3;

Documentation

The documentation is generate by Doxygen.

√ DO Write Doxygen documentation only in header file (.hpp).

√ DO All documentation comment must start by triple slash ///

/// @brief MyClass do something
class MyClass {
};

√ DO Doxygen command start with at-sign @

/// @brief my_func do something
/// @param name A string that contains the name.
/// @remarks The name must be begin by a uppercase; otherwise std::invalid_argument throws.
/// @exception std::invalid_argument name not started by uppercase.
void my_func(const std::sstring& name) {
};

This example of doxygen documented class (application_context.hpp) shows somes doxygen commands:

#pragma once
#include "form.hpp"

/// @brief The xtd namespace contains all fundamental classes to access Hardware, Os, System, and more.
namespace xtd {
  /// @brief The xtd::forms namespace contains classes for creating Windows-based applications that take full advantage of the rich user interface features available in the Microsoft Windows operating system, Apple macOS and Linux like Ubuntu operating system.
  namespace forms {
    /// @cond
    class application;
    /// @endcond
    
    /// @brief Specifies the contextual information about an application thread.
    /// @remarks You can use the application_context class to redefine the circumstances that cause a message loop to exit. By default, the application_context listens to the closed event on the application's main form, then exits the thread's message loop.
    /// @par Example
    /// The following code example demonstrate the use of application and application_context classes.
    /// @include application_context.cpp
    class application_context {
    public:
      /// @brief Initializes a new instance of the application_context class with no context.
      application_context() = default;
      /// @brief Initializes a new instance of the application_context class with the specified Form.
      /// @param main_form The main form of the application to use for context.
      /// @remarks If on_main_form_closed is not overridden, the message loop of the thread terminates when main_form is closed.
      explicit application_context(const form& main_form) {this->main_form(main_form);}

      /// @cond
      virtual ~application_context() {
        if (this->main_form_ != nullptr) this->main_form_->handle_destroyed -= {*this, &application_context::on_main_form_closed};
      }
      /// @endcond
      
      /// @brief Gets the form to use as context.
      /// @return The form to use as context.
      /// @remarks This property determines the main form for this context. This property can change at any time. If on_main_form_closed is not overridden, the message loop of the thread terminates when the main_form parameter closes.
      const form& main_form() const {return *this->main_form_;}
      /// @brief Gets or sets the Form to use as context.
      /// @return The form to use as context.
      /// @remarks This property determines the main form for this context. This property can change at any time. If on_main_form_closed is not overridden, the message loop of the thread terminates when the main_form parameter closes.
      form& main_form() {return *this->main_form_;}
      /// @brief Sets the Form to use as context.
      /// @param main_form The form to use as context.
      /// @remarks This property determines the main form for this context. This property can change at any time. If on_main_form_closed is not overridden, the message loop of the thread terminates when the main_form parameter closes.
      void main_form(const form& main_form) {
        if (this->main_form_ != nullptr) this->main_form_->handle_destroyed -= {*this, &application_context::on_main_form_closed};
        this->main_form_ = const_cast<form*>(&main_form);
        this->main_form_->handle_destroyed += {*this, &application_context::on_main_form_closed};
      }

      /// @brief Gets an object that contains data about the control.
      /// @return A std::any that contains data about the control. The default is empty.
      /// @remarks Any type of class can be assigned to this property.
      /// @remarks A common use for the tag property is to store data that is closely associated with the control. For example, if you have a control that displays information about a customer, you might store a data_set that contains the customer's order history in that control's tag property so the data can be accessed quickly.
      std::any tag() const {return this->tag_;}
      /// @brief Sets an object that contains data about the control.
      /// @param tag A std::any that contains data about the control. The default is empty.
      /// @remarks Any type of class can be assigned to this property.
      /// @remarks A common use for the tag property is to store data that is closely associated with the control. For example, if you have a control that displays information about a customer, you might store a data_set that contains the customer's order history in that control's tag property so the data can be accessed quickly.
      void tag(std::any tag) {this->tag_ = tag;}

      /// @brief Occurs when the message loop of the thread should be terminated, by calling exit_thread().
      event<application_context, event_handler<const application_context&>> thread_exit;
      
      /// @brief Terminates the message loop of the thread.
      /// @remarks This method calls exit_thread_core.
      /// @note exit_thread and exit_thread_core do not actually cause the thread to terminate. These methods raise the thread_exit event to which the Application object listens. The Application object then terminates the thread.
      void exit_thread() {this->exit_thread_core();}
      
    protected:
      /// @brief Terminates the message loop of the thread.
      /// @remarks This method is called from exit_thread.
      /// @note exit_thread and exit_thread_core do not actually cause the thread to terminate. These methods raise the thread_exit event to which the Application object listens. The Application object then terminates the thread.
      virtual void exit_thread_core() {this->thread_exit(*this, event_args::empty);}
      
      /// @brief Calls ExitThreadCore(), which raises the ThreadExit event.
      /// @param sender The object that raised the event.
      /// @param e The event_args that contains the event data.
      /// @remarks The default implementation of this method calls exit_thread_core.
      virtual void on_main_form_closed(const control& sender, const event_args& e) {
        if (!this->main_form_->recreating_handle()) {
          this->main_form_->handle_destroyed -= {*this, &application_context::on_main_form_closed};
          this->exit_thread_core();
        }
      }
      
    private:
      /// @cond
      friend class application;
      /// @endcond
      form* main_form_ = nullptr;
      std::any tag_;
    };
  }
}

For more commands see Doxygen Special commands and for more informations see Doxygen Manual.

Indentation

√ DO Indent block contents

namespace test {
  class aclass {
    void method() {
      int x;
      int y;
    }
  };
}

X DO NOT Indent open and close braces

class aclass {
  int afield;

  void method() {
  }
};

X DO NOT Indent switch sections

class aclass {
  void method(int x) {
    switch (x) {
    case 1:
      break;
    }
  }
};

√ DO Indent case sections

class aclass {
  void method(int x) {
    switch (x) {
    case 1:
      break;
    }
  }
};

X DO NOT Indent label

class test {
  void method() {
  label:
    console::write_line("Hello World");
  }
};

New lines

New line options for braces

X DO NOT Place open brace on new line for types

class example {
};

X DO NOT Place open brace on new line for methods

void example() {
}

X DO NOT Place open brace on new line for lambda expressions

void example() {
  auto del = [](int i, int j) {
  };
}

X DO NOT Place open brace on new line for control blocks

void example() {
  if (true) {
  }
}

X DO NOT Place open brace on new line for object initializers

void example() {
  std::vector<int> array_list {
    42, 24, 84
  };
}

New line options for keywords

X DO NOT Place "else" on new line

void example() {
  if (true) {
    // ...
  } else {
    // ...
  }
}

X DO NOT Place "catch" on new line

void example() {
  try {
    // ...
  } catch(...) {
    // ...
  }
}

New line options for expressions

X DO NOT Place memberin object initializers on new line

void example() {
  xtd::drawing::point p {
    10, 24
  };
}

Spacing

Set spacing for method declarations

X DO NOT Insert space between method name and its opening parenthesis

void example() {
}

X DO NOT Insert space within argument list parentheses

void example(int i, int j) {
}

X DO NOT Insert space within empty argument list parentheses

void example() {
}

Set spacing for method calls

X DO NOT Insert space between method name and its opening parenthesis

void example() {
  test();
}

X DO NOT Insert space within argument list parentheses

void example() {
  test(int i, int j);
}

X DO NOT Insert space within empty argument list parentheses

void example() {
  test();
}

Set other spacing options

√ DO Insert space after keywords in control flow statements

void example() {
  if (condition) {
  }
}

X DO NOT Insert space within parentheses of expressions

void example() {
  i = (5 + 3) * 2;
}

X DO NOT Insert space within parentheses of type casts

void example() {
  test = (const itest&)o;
}

X DO NOT Insert space within parentheses of control flow statements

void example() {
  if (condition) {
  }
}

X DO NOT Insert space after casts

void example() {
  test = (const itest&)o;
}

√ DO Insert space in declaration statements

void example() {
  int x = 5;
}

Set spacing for square brackets

X DO NOT Insert space before open square bracket

void example() {
  i[5] = 3;
}

X DO NOT Insert space within empty square brackets

void example() {
  test(int[] {1, 2});
}

X DO NOT Insert space within square brackets

void example() {
  i[5] = 3;
}

Set spacing for brackets

√ DO Insert space after colon for base or interface in type declaration

class foo : public bar {
}

√ DO Insert space after comma

void example() {
  int i = 0, j = 15;
}

X DO NOT Insert space after dot

void example() {
  foo.bar().test();
}

X DO NOT Insert space after structure or class dereference

void example() {
  foo->bar()->test();
}

√ DO Insert space after semicolon in "for" statement

void example() {
  for (int i = 0; i < 10; i++) {
  }
}

√ DO Insert space before colon for base or interface in type declaration

class foo : public bar {
}

X DO NOT Insert space before dot

void example() {
  foo.bar().test();
}

X DO NOT Insert space before structure or class dereference

void example() {
  foo->bar()->test();
}

X DO NOT Insert space before semicolon in "for" statement

void example() {
  for (int i = 0; i < 10; i++) {
  }
}

√ DO Set spacing for operators

void example() {
  i = (5 + 3) * 2;
}

See also

​ Other Resources


© 2020 Gammasoft.