ACF $AcfVersion:0$
ACF - Application Component Framework

Introduction

ACF (Application Component Framework) is a comprehensive C++ based, cross-platform component framework that was especially designed for creation of complex, customizable and highly scalable applications. The framework provides a robust foundation for building industrial-strength software systems with emphasis on modularity, reusability, and maintainability.

Key Principles

ACF follows the component-oriented programming paradigm and provides instruments to build software from reusable, loosely-coupled components. The framework serves well-defined interfaces and concepts to create those components with the following core principles:

  • Separation of Concerns: Clear boundaries between business logic, data model, and presentation layer
  • Interface-Based Communication: Components interact exclusively through well-defined interfaces
  • Dependency Injection: Automatic resolution and injection of component dependencies
  • Design Pattern Implementation: Built-in support for common patterns (Factory, Observer, Serialization, etc.)
  • Type Safety: Strong typing throughout the framework with compile-time checking where possible
  • Cross-Platform Support: Runs on Windows, Linux, and macOS

Technical Foundation

ACF contains a set of libraries with implementations of most useful design patterns:

  • Serialization: Archive-based persistence with multiple backend support (XML, JSON, Binary)
  • Model/Observer: Sophisticated change notification and data binding mechanisms
  • Factory Pattern: Dynamic component instantiation with registry system
  • Dependency Injection: Automatic dependency resolution and lifecycle management
  • Document/View Architecture: Complete MDI/SDI application framework
  • Parameter Management: Type-safe parameter handling with GUI integration

The UI-part of the framework is based on Qt library provided by Qt Company, providing native look-and-feel across platforms and extensive widget support.

ACF implements a powerful component concept and includes many well-designed components, which you can directly use in your application, significantly reducing development time and improving code quality.

ACF is open source and released under the terms of the GNU Lesser General Public License (LGPL), allowing use in both open source and commercial applications.

Theoretical Background

More theoretical considerations about component-based development can be found at:

How ACF Works

Component Architecture

The main idea behind ACF is to see each software product as a composition of components with clearly defined interfaces. Interface-based communication ensures loose coupling and high testability.

Interface is the only way for communication between components, which provides:

  • Clear API contracts between components
  • Easy mocking for unit tests
  • Runtime component replacement (plugin architecture)
  • Version compatibility through interface stability

Implementing Components

The typical workflow to implement an ACF component involves:

1. Define the Interface

A C++ pure virtual interface must be defined, inheriting from istd::IPolymorphic (or a derived interface like iser::ISerializable):

// Define the interface
class IDataProcessor : virtual public istd::IPolymorphic
{
public:
virtual bool ProcessData(const QString& input, QString& output) = 0;
virtual void SetProcessingMode(int mode) = 0;
};
Base interface for all used interfaces and implementations.

Note: You typically don't inherit from icomp::IComponent directly - it's an internal framework interface. Use istd::IPolymorphic or iser::ISerializable as the base.

2. Implement the Component Class

Create a class that implements this interface. There are several approaches:

a) Basic Component Implementation:

// Implement the component
class CDataProcessor :
virtual public IDataProcessor
{
public:
typedef icomp::CComponentBase BaseClass;
// Component initialization
I_BEGIN_COMPONENT(CDataProcessor);
I_REGISTER_INTERFACE(IDataProcessor);
I_END_COMPONENT;
CDataProcessor() : m_mode(0) {}
// Implement interface methods
virtual bool ProcessData(const QString& input, QString& output) override
{
output = input.toUpper(); // Example processing
return true;
}
virtual void SetProcessingMode(int mode) override
{
m_mode = mode;
}
private:
int m_mode;
};
Base class for component implementation.

b) Component with References (Dependencies):

Components can declare references to other components for dependency injection:

class CAdvancedProcessor :
virtual public IDataProcessor
{
public:
typedef icomp::CComponentBase BaseClass;
I_BEGIN_COMPONENT(CAdvancedProcessor);
I_REGISTER_INTERFACE(IDataProcessor);
// Declare reference to another component
I_ASSIGN_INTERFACE_REFERENCE(ILogger, m_loggerRefPtr, "Logger", "Logging component", false);
I_END_COMPONENT;
virtual bool ProcessData(const QString& input, QString& output) override
{
// Access referenced component
istd::ILogger* logger = GetReferenceValue(m_loggerRefPtr);
if (logger)
logger->LogMessage("Processing data...");
output = input.toUpper();
return true;
}
virtual void SetProcessingMode(int mode) override {}
private:
// Reference pointer
I_REF_PTR(istd::ILogger, m_loggerRefPtr);
};
Common interface for classes sending some log info.
Definition ILogger.h:23

c) Component with Attributes:

Attributes allow configuration of component behavior:

class CConfigurableProcessor :
virtual public IDataProcessor
{
public:
typedef icomp::CComponentBase BaseClass;
I_BEGIN_COMPONENT(CConfigurableProcessor);
I_REGISTER_INTERFACE(IDataProcessor);
// Declare attributes with defaults
I_ASSIGN(m_maxLengthAttrPtr, "MaxLength", "Maximum input length", false, 100);
I_ASSIGN(m_enableLoggingAttrPtr, "EnableLogging", "Enable logging", false, true);
I_END_COMPONENT;
virtual bool ProcessData(const QString& input, QString& output) override
{
// Access attribute values
int maxLength = GetAttributeValue(m_maxLengthAttrPtr);
bool enableLogging = GetAttributeValue(m_enableLoggingAttrPtr);
if (input.length() > maxLength)
return false;
if (enableLogging)
qDebug() << "Processing:" << input;
output = input.toUpper();
return true;
}
virtual void SetProcessingMode(int mode) override {}
protected:
virtual void OnComponentCreated() override
{
BaseClass::OnComponentCreated();
// Initialize component here - attributes and references are now available
}
private:
// Attribute pointers
I_ATTR(int, m_maxLengthAttrPtr);
I_ATTR(bool, m_enableLoggingAttrPtr);
};
virtual void OnComponentCreated()

3. Register in a Package

After implementation, components must be registered in a Package. Packages are logical containers that group related components:

Package Types:

  • C++ Packages (DLL/Shared Library): For compiled C++ components with special export interface
  • Composition Packages (ARX files): For visual component compositions created with ACF Compositor

All packages use the extension .ARP (ACF Registry Package) for consistency.

// Package registration example
ICOMP_REGISTER_COMPONENT(CDataProcessor)
ICOMP_REGISTER_COMPONENT(CAdvancedProcessor)
ICOMP_REGISTER_COMPONENT(CConfigurableProcessor)

Component Composition

Components can be combined into larger components:

ACF Compositor Tool:

  • Graphical editor for component dependencies and attributes
  • UML-like visualization of component structure
  • Visual connection of component references
  • Attribute configuration through property editors
  • Export to ARX files (registry format)

Application Execution

There are two deployment strategies:

1. Runtime Execution (Prototyping):

  • Component compositions run directly by Framework-Runtime
  • Dynamic loading of component packages
  • Useful for rapid prototyping and testing
  • Hot-swapping of components during development

2. Compiled Execution (Production):

  • ACF provides ARX Compiler (ARXC) - a source code generator
  • Converts component compositions to native C++ code
  • Resulting code is compiled normally
  • Advantages:
    • No runtime DLL loading overhead
    • Better performance
    • Reduced deployment complexity
    • Static linking possible
    • Better optimization by compiler

Development Workflow Summary

  1. Design: Define interfaces and component contracts
  2. Implement: Create component classes with dependencies and attributes
  3. Compose: Use ACF Compositor to create component compositions
  4. Test: Run with Framework-Runtime for rapid testing
  5. Compile: Generate C++ code with ARX Compiler
  6. Deploy: Build and distribute optimized executable

Key Features and Capabilities

ACF provides a comprehensive set of features for enterprise-grade application development:

Architectural Features

1. Component Framework (icomp)

  • Component model with lifecycle management
  • Interface-based programming with IComponent base
  • Component registry and factory system
  • Automatic dependency injection and resolution
  • Attribute system for component configuration
  • Component composition and aggregation
  • Plugin architecture with dynamic loading
  • Type-safe component casting and querying

2. Graphical Component Editing

  • ACF Compositor: Visual UML-like component editor
  • Drag-and-drop component composition
  • Visual dependency wiring
  • Property editing with live preview
  • Export to ARX (ACF Registry XML) format
  • Validation and error checking

3. Code Generation

  • ARX Compiler (ARXC): Component composition to C++ converter
  • Generates efficient, readable C++ code
  • Preserves component structure and dependencies
  • Enables static linking and optimization
  • Reduces runtime overhead
  • Facilitates debugging with source-level access

Data Management Features

4. Type-Safe Parameter Management (iprm)

  • Strongly typed parameter interfaces
  • Runtime type checking and validation
  • Parameter grouping and hierarchies
  • Default values and constraints
  • Change notification integration
  • GUI auto-generation support
  • Serialization support for all parameter types

5. Comprehensive Serialization (iser)

  • Archive-based abstraction layer
  • Multiple format support:
    • Binary archives for performance
    • XML (simple and compact) for interoperability
    • JSON for web integration
    • Memory archives for networking
    • Bitwise archives for compression
  • Extensible architecture for custom formats
  • Support for complex object graphs
  • Version compatibility mechanisms

6. Document Management (idoc, iqtdoc)

  • Template-based document framework
  • Full undo/redo support with command pattern
  • Multiple document interface (MDI) support
  • Single document interface (SDI) support
  • Document import/export with multiple formats
  • Print preview and printing support
  • Recent files management
  • Auto-save functionality

User Interface Features

7. Qt Integration (iqtgui, iqtprm)

  • Native Qt widget integration
  • Automatic UI generation from parameters
  • Custom widget library (iwidgets)
  • Drag-and-drop support
  • Docking and toolbar management
  • Splash screens and progress dialogs
  • Designer plugin support
  • Style sheet support

8. 2D/3D Graphics (i2d, i3d, iview)

  • Geometric primitives (points, lines, polygons, curves)
  • Transformations (translation, rotation, scaling)
  • Calibration support for real-world measurements
  • Interactive shapes with selection and manipulation
  • Calibrated views with zoom and pan
  • 3D transformations and projections
  • OpenGL integration support

Development Support Features

9. Testing Framework (itest)

  • Qt Test-based unit testing
  • Component testing utilities
  • Mock component support
  • Test data management
  • Automated test discovery
  • Performance benchmarking
  • Code coverage integration

10. Logging System (ilog, iloggui)

  • Multi-level logging (Debug, Info, Warning, Error)
  • Multiple output targets (console, file, GUI)
  • Thread-safe logging
  • Structured log messages
  • Log filtering and search
  • GUI log viewer with color coding
  • Export functionality

11. File Handling (ifile, ifilegui)

  • Generic file loading/saving interface
  • Format auto-detection
  • File dialogs with preview
  • Recent files tracking
  • Path management utilities
  • Auto-persistence support
  • File watchers for change detection

Integration Features

12. Third-Party Library Wrappers

ACF provides component wrappers for popular libraries:

  • Boost: Smart pointers, algorithms, utilities
  • MongoDB: NoSQL database integration
  • PostgreSQL: Relational database support
  • Qwt: Scientific plotting and graphing
  • Qwt3D: 3D surface plotting
  • OpenCV: Computer vision and image processing
  • Phonon: Multimedia playback
  • FFmpeg: Video encoding/decoding
  • zlib: Compression
  • QScintilla: Source code editing

13. Package Management (ipackage)

  • Dynamic package loading
  • Plugin discovery and enumeration
  • Package dependencies management
  • Version compatibility checking
  • Package metadata and descriptions
  • Hot-reloading support (development mode)

Advanced Features

14. Model/Observer Pattern (imod)

  • Sophisticated change notification
  • Hierarchical model support
  • Selective observation (filter by change type)
  • Automatic observer lifecycle management
  • Multi-threaded observer support
  • Change delegation chains

15. Color Management (icmm)

  • Multiple color models (RGB, HSV, CMYK, Lab)
  • Color space conversions
  • Color interpolation
  • Palette management
  • Color calibration support

16. Mathematical Utilities (imath)

  • Interpolation algorithms (linear, spline, polynomial)
  • Complex number operations
  • Numerical algorithms
  • Statistical functions
  • Matrix operations
  • Curve fitting

Image Processing Features

17. Imaging Components (iimg)

  • Bitmap handling and manipulation
  • Multiple format support (PNG, JPEG, BMP, TIFF)
  • Color space conversions
  • Filtering and transformations
  • ROI (Region of Interest) support
  • Histogram operations
  • Image metadata handling

ACF Libraries Reference

ACF is organized into focused, cohesive libraries that can be used independently or together. Each library provides detailed documentation with examples and best practices.

Core Foundation Libraries

These libraries form the foundation of the framework:

istd - Standard Utilities

icomp - Component Framework

  • Comprehensive component-based architecture with dependency injection
  • Core interfaces: icomp::IComponent, icomp::IRegistry, icomp::IComponentFactory
  • Attribute system for component configuration
  • Automatic dependency resolution and lifecycle management
  • See icomp - Component Framework for complete guide

iser - Serialization Framework

iprm - Parameter Management

Data and Mathematics

imath - Mathematical Utilities

  • Numerical algorithms (interpolation, complex numbers, curve fitting)
  • Vector and matrix operations
  • Statistical functions and numerical solvers
  • See imath - Mathematical Utilities Library for details

i2d - 2D Graphics Utilities

  • 2D geometric primitives (points, lines, polygons, circles)
  • Affine transformations and geometric calculations
  • Calibration support for real-world measurements
  • See i2d - 2D Graphics Utilities Library for comprehensive documentation

i3d - 3D Graphics Utilities

icmm - Color Management

  • Multiple color models (RGB, HSV, CMYK, Lab)
  • Color space conversions and interpolation
  • Palette management and calibration
  • See icmm - Color Management Library for comprehensive guide

Document and View Framework

idoc - Document Framework

iview - View Framework

  • Interactive shapes and calibrated views
  • Selection, manipulation, zoom and pan support
  • See iview - View Framework for documentation

imod - Model-Observer Pattern

File and Data Handling

ifile - File Handling

  • Generic file operations with format auto-detection
  • Archive implementations for files (Binary, XML, JSON)
  • See ifile - File Handling Library for details

ifilegui - File GUI Components

iimg - Imaging

  • Image loading, manipulation and display
  • Multiple format support and color space operations
  • See iimg - Imaging Library for comprehensive guide

Logging and Testing

ilog - Logging

  • Multi-level logging infrastructure (Debug, Info, Warning, Error)
  • Thread-safe logging with multiple output targets
  • See ilog - Logging Library for details

iloggui - Logging GUI

itest - Testing Framework

  • Qt Test-based unit testing support
  • Component testing utilities and assertion helpers
  • See itest - Testing Framework for testing guide

Qt Framework Integration

iqt - Qt Utilities

iqt2d - Qt 2D Graphics

iqtdoc - Qt Document Framework

iqtgui - Qt GUI Utilities

iqtprm - Qt Parameter Widgets

iwidgets - Widget Utilities

Infrastructure Libraries

iattr - Attributes

ibase - Base Components

ipackage - Package Management

Additional Resources

Tutorials and Examples

  • Component Framework Guide: Comprehensive guide to building components (see Docs/ComponentFramework.md)
  • Component Examples: Practical implementation examples (see Docs/ComponentFrameworkExamples.md)
  • Document/View Framework: Building document-based applications (see Docs/DocumentViewFrameworkREADME.md)

Architecture Guides

Application Frameworks

Building ACF

Prerequisites

Required Software:

  • C++ compiler with C++11 support or later
  • Qt Framework (version 5.x or 6.x)
  • CMake or qmake build system
  • Doxygen (for documentation generation)

Optional Dependencies:

  • Boost (for extended functionality)
  • OpenCV (for image processing components)
  • Qwt/Qwt3D (for plotting components)
  • Other third-party libraries as needed

Build Process

ACF uses a standard CMake or qmake build process:

  1. Configure the environment: Set ACFDIR environment variable to the ACF installation directory
  2. Generate build files: Use CMake or qmake to generate platform-specific build files
  3. Build libraries: Build the core libraries in dependency order
  4. Build applications: Build applications and tools
  5. Run tests: Execute the test suite to verify the build

Example Build Commands:

# Set environment variable
export ACFDIR=/path/to/acf
# Create build directory
mkdir build && cd build
# Configure with CMake
cmake ..
# Build
make -j8
# Run tests
ctest

Deployment Options

ACF supports multiple deployment strategies:

1. Development Mode:

  • Dynamic component loading from DLL/shared libraries
  • Runtime composition with ARX files
  • Hot-reloading support for rapid iteration
  • Use ACF Compositor for visual editing

2. Production Mode:

  • Compile component compositions to C++ using ARX Compiler (ARXC)
  • Static linking of components into executable
  • Optimized performance with compiler optimizations
  • Reduced deployment size and complexity

3. Plugin Mode:

  • Package components as ARP files (ACF Registry Package)
  • Dynamic discovery and loading of plugins
  • Extensible application architecture
  • Update plugins without recompiling main application

Getting Started

Quick Start Guide

1. Define an Interface

// MyInterface.h
class IMyProcessor : virtual public istd::IPolymorphic
{
public:
virtual bool Process(const QString& input, QString& output) = 0;
};

2. Implement a Component

// MyComponent.h
#include "MyInterface.h"
class CMyProcessor :
virtual public IMyProcessor
{
public:
typedef icomp::CComponentBase BaseClass;
I_BEGIN_COMPONENT(CMyProcessor);
I_REGISTER_INTERFACE(IMyProcessor);
I_END_COMPONENT;
CMyProcessor();
// Implement interface
virtual bool Process(const QString& input, QString& output) override;
};
// MyComponent.cpp
CMyProcessor::CMyProcessor()
{
}
bool CMyProcessor::Process(const QString& input, QString& output)
{
output = input.toUpper();
return true;
}

3. Register and Use

Components are registered in package registration files and accessed through the component registry:

// Package registration (in .cpp file)
ICOMP_REGISTER_COMPONENT(CMyProcessor)
// Usage - accessing via registry
icomp::IRegistry* registry = GetRegistry();
IMyProcessor* processor = registry->QueryInterface<IMyProcessor>("MyProcessor");
if (processor)
{
QString result;
processor->Process("hello", result);
// result = "HELLO"
}
Interface representing information stored in component registry.
Definition IRegistry.h:48

Learning Resources

Design Patterns in ACF

ACF implements many proven design patterns:

Creational Patterns:

  • Factory Pattern: icomp::IComponentFactory for dynamic component creation
  • Abstract Factory: Component families through package system
  • Singleton: Registry and environment management
  • Builder: Component composition with ACF Compositor

Structural Patterns:

  • Composite: Hierarchical component composition (core concept)
  • Proxy: imod::CModelProxy for delegation
  • Adapter: Archive adapters for different formats
  • Facade: High-level library interfaces

Behavioral Patterns:

  • Observer: istd::IChangeable and imod::IModelObserver
  • Strategy: Interface-based component implementations
  • Command: Undo/redo in document framework
  • Template Method: Component lifecycle hooks

Best Practices and Guidelines

Component Design

  1. Interface Segregation: Define focused, single-purpose interfaces
  2. Dependency Injection: Use references for component dependencies
  3. Immutable IDs: Component IDs should not change after creation
  4. Loose Coupling: Communicate only through interfaces
  5. Composition Over Inheritance: Prefer component composition

Error Handling

  1. Return Value Checking: Check return values from all operations
  2. Change Notification Scoping: Use istd::CChangeNotifier for RAII
  3. Archive Error Handling: Verify archive state after operations
  4. Validation: Validate parameters and constraints before processing
  5. Logging: Use ilog for diagnostic information

Performance Considerations

  1. Lazy Initialization: Components support lazy reference resolution
  2. Batch Changes: Group related changes with istd::CChangeGroup
  3. Binary Archives: Use binary archives for performance-critical serialization
  4. Smart Pointers: Use appropriate smart pointer types to avoid overhead
  5. Static Linking: Compile compositions for production deployment

Thread Safety

  1. Most ACF components are not thread-safe by default
  2. Use Qt's signal/slot mechanism for cross-thread communication
  3. Use iqtgui::TGuiObserverWrap for GUI updates from worker threads
  4. Synchronize access to shared components with mutexes
  5. Consider thread-local component instances for parallel processing

Troubleshooting and FAQ

Common Issues

Q: Component not found in registry

  • Verify component is registered with ICOMP_REGISTER_COMPONENT
  • Check package is loaded correctly
  • Ensure component ID matches in registry and lookup

Q: Dependency injection not working

  • Verify reference ID matches target component ID
  • Check component hierarchy and scope
  • Ensure referenced component is created before referencing component

Q: Serialization fails

  • Implement iser::ISerializable correctly
  • Check archive is in correct mode (reading/writing)
  • Verify Serialize() is symmetric for read/write
  • Add version information for compatibility

Q: GUI not updating on model change

Q: Memory leaks detected

  • Use smart pointers (istd::TUniqueInterfacePtr, TSharedInterfacePtr)
  • Check for circular references
  • Verify component lifecycle management
  • Use memory profiling tools to identify sources

Debug Tips

  1. Enable Logging: Use ilog with Debug level for detailed information
  2. Inspect Registry: Use registry traversal to verify component structure
  3. Test in Isolation: Unit test components separately before integration
  4. Check Archives: Export to XML to inspect serialized data
  5. Use Compositor: Visualize component connections graphically

Screenshots and Examples

ACF Compositor - Visual Component Editing

ACF Compositor provides a graphical interface for:

  • Creating and editing component compositions
  • Visual dependency wiring between components
  • Property and attribute configuration
  • UML-like component diagrams
  • Export to ARX format for runtime or compilation
Multi-Document Application Framework

Document Framework example showing:

  • Multiple document interface (MDI) with docking windows
  • Integrated parameter editing panels
  • Log viewer and diagnostic tools
  • Menu and toolbar customization
  • Full undo/redo support
HTTP-based Server Framework

Server Framework demonstrating:

  • Component-based server architecture
  • RESTful API implementation with components
  • Modular request handling
  • Extensible service architecture

License and Contributing

License Information

ACF is open source software released under the GNU Lesser General Public License (LGPL).

Key Points:

  • Free to use in both open source and commercial applications
  • Modifications to ACF itself must be shared under LGPL
  • Applications using ACF can be proprietary
  • See LGPL directory for complete license text

Contributing to ACF

Contributions are welcome! To contribute:

  1. Fork the repository on GitHub
  2. Create a feature branch
  3. Follow the existing coding conventions
  4. Add tests for new functionality
  5. Update documentation as needed
  6. Submit a pull request

Repository: https://github.com/ImagingTools/Acf

Documentation: https://imagingtools.github.io/Acf/

Support and Contact

  • Issues: Report bugs and feature requests on GitHub
  • Documentation: Read the comprehensive guides and API reference
  • Examples: Study the example code in the repository
  • Community: Engage with other developers using ACF