Skip to main content
Version: Latest

Region Building with Position Integration

Create regions using flexible positioning with the RegionBuilder and Position integration for precise placement.

Overview

The RegionBuilder class provides a fluent API for creating regions with precise positioning. By integrating with the Position class and Positions.Name enum, it offers both absolute pixel positioning and percentage-based placement options.

Key Features

  • Absolute Positioning: Define regions using exact pixel coordinates
  • Position Integration: Leverage the Position class for percentage-based placement
  • Named Positions: Use semantic positions like TOPLEFT, MIDDLEMIDDLE, BOTTOMRIGHT
  • Relative Positioning: Position regions relative to other regions
  • Percentage-Based Sizing: Define regions as percentages of screen size
  • Fluent API: Chain methods for readable region construction

Basic Usage

Creating a RegionBuilder

import io.github.jspinak.brobot.model.element.Region;
import io.github.jspinak.brobot.model.element.RegionBuilder;
import io.github.jspinak.brobot.model.element.Position;
import static io.github.jspinak.brobot.model.element.Positions.Name.*;

// Access the builder through Region's static method
Region region = Region.builder()
.withSize(200, 150)
.build();

Absolute Positioning

// Simple region with absolute coordinates
Region absolute = Region.builder()
.withRegion(100, 100, 200, 150) // x, y, width, height
.build();

// Position and size separately
Region separate = Region.builder()
.withPosition(50, 75)
.withSize(300, 200)
.build();

Position-Based Placement

Using Position Objects

The Position class provides percentage-based coordinates (0.0 to 1.0) for resolution-independent placement:

// Place region at 70% width, 30% height of screen
Region customPos = Region.builder()
.withSize(200, 150)
.withPosition(new Position(0.7, 0.3))
.build();

// Center of screen using Position
Region centered = Region.builder()
.withSize(400, 300)
.withPosition(new Position(0.5, 0.5))
.build();

Named Positions

Use the Positions.Name enum for semantic positioning:

// Quick placement using named positions
Region topRight = Region.builder()
.withSize(300, 200)
.withPosition(TOPRIGHT)
.build();

Region bottomCenter = Region.builder()
.withSize(250, 100)
.withPosition(BOTTOMMIDDLE)
.build();

// All available named positions:
// TOPLEFT, TOPMIDDLE, TOPRIGHT
// MIDDLELEFT, MIDDLEMIDDLE, MIDDLERIGHT
// BOTTOMLEFT, BOTTOMMIDDLE, BOTTOMRIGHT

Convenience Methods

RegionBuilder provides helper methods for common positions:

// Center on screen
Region dialog = Region.builder()
.withSize(600, 400)
.centerOnScreen()
.build();

// Corner positions
Region topLeft = Region.builder()
.withSize(100, 100)
.topLeft()
.build();

Region bottomRight = Region.builder()
.withSize(120, 80)
.bottomRight()
.build();

// Edge positions
Region topBar = Region.builder()
.withScreenPercentageSize(1.0, 0.1) // Full width, 10% height
.topCenter()
.build();

Region sidebar = Region.builder()
.withScreenPercentageSize(0.2, 1.0) // 20% width, full height
.leftCenter()
.build();

Screen Percentage Sizing

Define regions as percentages of screen dimensions:

// Size as percentage of screen
Region halfScreen = Region.builder()
.withScreenPercentageSize(0.5, 0.5) // 50% width, 50% height
.centerOnScreen()
.build();

// Position and size using percentages
Region searchArea = Region.builder()
.withScreenPercentage(0.1, 0.1, 0.8, 0.3) // x%, y%, width%, height%
.build();

// Just percentage size (position separately)
Region percentSized = Region.builder()
.withScreenPercentageSize(0.3, 0.4)
.topRight()
.build();

Relative Positioning

Position regions relative to other regions:

Region mainWindow = Region.builder()
.withSize(800, 600)
.centerOnScreen()
.build();

// Position tooltip above the main window
Region tooltip = Region.builder()
.withSize(200, 50)
.positionRelativeTo(mainWindow, TOPMIDDLE)
.adjustY(-10) // 10px gap above
.build();

// Position button in bottom-right of window
Region button = Region.builder()
.withSize(100, 40)
.positionRelativeTo(mainWindow, BOTTOMRIGHT)
.adjustX(-10) // 10px margin from right
.adjustY(-10) // 10px margin from bottom
.build();

// Custom relative position (25% from left, 75% from top)
Region marker = Region.builder()
.withSize(20, 20)
.positionRelativeTo(mainWindow, new Position(0.25, 0.75))
.build();

Predefined Screen Regions

Quick methods for common screen divisions:

// Full screen
Region fullScreen = Region.builder()
.fullScreen()
.build();

// Half regions
Region topHalf = Region.builder()
.topHalf()
.build();

Region bottomHalf = Region.builder()
.bottomHalf()
.build();

Region leftHalf = Region.builder()
.leftHalf()
.build();

Region rightHalf = Region.builder()
.rightHalf()
.build();

Adjustments and Modifications

Fine-tuning Position and Size

// Adjust individual dimensions
Region adjusted = Region.builder()
.withRegion(100, 100, 200, 150)
.adjustX(10) // Move 10px right
.adjustY(-20) // Move 20px up
.adjustWidth(50) // Increase width by 50px
.adjustHeight(30) // Increase height by 30px
.build();

// Adjust all at once
Region bulkAdjusted = Region.builder()
.withRegion(100, 100, 200, 150)
.adjustBy(10, -5, 20, 20) // x, y, width, height adjustments
.build();

Expanding and Contracting

// Expand region by pixels on all sides
Region expanded = Region.builder()
.withRegion(100, 100, 200, 150)
.expand(20) // Grows by 20px on all sides
.build();
// Result: x=80, y=80, width=240, height=190

// Contract region (negative expansion)
Region contracted = Region.builder()
.withRegion(100, 100, 200, 150)
.expand(-10) // Shrinks by 10px on all sides
.build();

Working with Existing Regions

Region original = new Region(100, 100, 200, 150);

// Modify existing region
Region modified = Region.builder()
.fromRegion(original)
.adjustWidth(50)
.adjustHeight(50)
.build();

// Create region relative to existing
Region adjacent = Region.builder()
.fromRegion(original)
.adjustX(original.getW() + 10) // Position to the right
.build();

Custom Anchoring

Control how regions are positioned using anchor points:

// Default anchor is TOPLEFT (0.0, 0.0)
Region defaultAnchor = Region.builder()
.withSize(100, 100)
.withPosition(500, 300) // Top-left corner at (500, 300)
.build();

// Center anchor - position specifies center point
Region centerAnchor = Region.builder()
.withSize(100, 100)
.withAnchor(MIDDLEMIDDLE)
.withPosition(500, 300) // Center at (500, 300)
.build();

// Custom anchor point (75% width, 25% height)
Region customAnchor = Region.builder()
.withSize(100, 100)
.withAnchor(new Position(0.75, 0.25))
.withPosition(500, 300) // Anchor point at (500, 300)
.build();

Constraints

Screen Boundary Constraints

// Constrain to screen boundaries (default: true)
Region constrained = Region.builder()
.withPosition(10000, 10000) // Way off screen
.withSize(200, 150)
.constrainToScreen(true)
.build();
// Will be repositioned to stay within screen bounds

// Allow off-screen positioning
Region offScreen = Region.builder()
.withPosition(-50, -50)
.withSize(200, 150)
.constrainToScreen(false)
.build();
// Maintains negative coordinates

Aspect Ratio Maintenance

// Maintain aspect ratio when resizing
Region aspectLocked = Region.builder()
.withSize(400, 300) // 4:3 ratio
.maintainAspectRatio(true)
.withWidth(600) // Height automatically becomes 450
.build();

Complex Layout Examples

Dashboard Layout

// Create a dashboard with header, sidebar, and content area
Region header = Region.builder()
.withScreenPercentageSize(1.0, 0.1) // Full width, 10% height
.topCenter()
.build();

Region sidebar = Region.builder()
.withScreenPercentageSize(0.2, 0.9) // 20% width, 90% height
.positionRelativeTo(header, BOTTOMLEFT)
.build();

Region content = Region.builder()
.positionRelativeTo(sidebar, MIDDLERIGHT)
.withScreenPercentageSize(0.8, 0.9)
.build();

Region footer = Region.builder()
.withScreenPercentageSize(1.0, 0.05)
.bottomCenter()
.build();
// Semi-transparent overlay
Region overlay = Region.builder()
.fullScreen()
.build();

// Centered modal dialog
Region modal = Region.builder()
.withScreenPercentageSize(0.5, 0.6) // 50% width, 60% height
.centerOnScreen()
.build();

// Close button in modal's top-right
Region closeButton = Region.builder()
.withSize(30, 30)
.positionRelativeTo(modal, TOPRIGHT)
.adjustX(-10)
.adjustY(10)
.build();

Grid Layout

// Create a 3x3 grid of regions
List<Region> grid = new ArrayList<>();
double cellWidth = 0.33;
double cellHeight = 0.33;

for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
Region cell = Region.builder()
.withScreenPercentage(
col * cellWidth, // x position
row * cellHeight, // y position
cellWidth * 0.9, // width with gap
cellHeight * 0.9 // height with gap
)
.build();
grid.add(cell);
}
}

Best Practices

1. Use Percentages for Cross-Platform Compatibility

// Good: Percentage-based, works on any screen
Region adaptive = Region.builder()
.withScreenPercentageSize(0.3, 0.4)
.centerOnScreen()
.build();

// Avoid: Fixed pixels may not work on different screens
Region fixed = Region.builder()
.withRegion(640, 360, 640, 480)
.build();

2. Use Direct Coordinates for Pixel-Perfect Placement

// Specify exact pixel coordinates when precision is needed
Region precise = Region.builder()
.withPosition(500, 300)
.withSize(400, 200)
.build();

3. Use Named Positions for Clarity

// Clear intent
Region notification = Region.builder()
.withSize(300, 100)
.topRight()
.adjustX(-20)
.adjustY(20)
.build();

// Less clear
Region notification2 = Region.builder()
.withSize(300, 100)
.withAnchor(new Position(1.0, 0.0))
.build();

4. Combine Relative and Absolute Positioning

// Start with relative, fine-tune with absolute
Region precise = Region.builder()
.withScreenPercentageSize(0.25, 0.2)
.centerOnScreen()
.adjustX(-10) // Fine adjustments
.adjustY(5)
.build();

5. Use Percentage-Based Sizing for Flexibility

// Create regions that work well at any resolution
Region flexible = Region.builder()
.withScreenPercentage(0.1, 0.1, 0.8, 0.8) // 10% margins, 80% of screen
.build();

// Verify region is properly defined
assert flexible.isDefined();
assert flexible.getW() > 0 && flexible.getH() > 0;

Integration with Brobot Actions

Using RegionBuilder in State Definitions

@Component
public class LoginState implements State {

private final Region usernameField = Region.builder()
.withScreenPercentage(0.4, 0.4, 0.2, 0.05)
.build();

private final Region passwordField = Region.builder()
.positionRelativeTo(usernameField, BOTTOMMIDDLE)
.withSize(usernameField.getW(), usernameField.getH())
.adjustY(20)
.build();

private final Region loginButton = Region.builder()
.positionRelativeTo(passwordField, BOTTOMMIDDLE)
.withSize(100, 40)
.adjustY(30)
.build();

// Use in actions
public void login(String username, String password) {
action.perform(new ObjectCollection.Builder()
.withRegions(usernameField)
.click()
.type(username)
.build());

action.perform(new ObjectCollection.Builder()
.withRegions(passwordField)
.click()
.type(password)
.build());

action.perform(new ObjectCollection.Builder()
.withRegions(loginButton)
.click()
.build());
}
}

Dynamic Region Creation

public class AdaptiveSearch {

public Region getSearchAreaForScreen() {
// Detect current screen size and create appropriate search area
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

if (screenSize.width > 2000) {
// Large screen: search in center third
return Region.builder()
.withScreenPercentage(0.33, 0.33, 0.34, 0.34)
.build();
} else if (screenSize.width > 1400) {
// Medium screen: search in center half
return Region.builder()
.withScreenPercentageSize(0.5, 0.5)
.centerOnScreen()
.build();
} else {
// Small screen: search most of screen
return Region.builder()
.withScreenPercentage(0.1, 0.1, 0.8, 0.8)
.build();
}
}
}

Troubleshooting

Region Outside Screen Bounds

// Problem: Region appears cut off
Region problem = Region.builder()
.withPosition(1800, 1000)
.withSize(300, 200)
.build();

// Solution: Enable screen constraints
Region solution = Region.builder()
.withPosition(1800, 1000)
.withSize(300, 200)
.constrainToScreen(true) // Ensures region stays on screen
.build();

Size Issues

// Problem: Region too small for reliable clicking
Region tooSmall = Region.builder()
.withPosition(100, 100)
.withSize(5, 5) // Too small!
.build();

// Solution: Use appropriate minimum sizes
Region clickable = Region.builder()
.withPosition(100, 100)
.withSize(50, 30) // Reasonable click target
.build();

// Or use percentage-based sizing for flexibility
Region flexible = Region.builder()
.withScreenPercentage(0.1, 0.1, 0.05, 0.03) // 5% width, 3% height
.build();

Position Calculation Errors

// Problem: Unexpected position with custom anchor
Region unexpected = Region.builder()
.withSize(100, 100)
.withAnchor(MIDDLEMIDDLE) // Changes reference point
.withPosition(0, 0) // Now refers to center, not top-left
.build();

// Solution: Understand anchor behavior
// With MIDDLEMIDDLE anchor, position (0,0) means center at (0,0)
// So actual top-left will be at (-50, -50)

Summary

The enhanced RegionBuilder with Position integration provides:

  • Resolution Independence: Define once, run anywhere
  • Intuitive API: Named positions and percentage-based sizing
  • Flexibility: Combine relative and absolute positioning
  • Maintainability: Clear, readable region definitions
  • Adaptability: Automatic scaling between resolutions

Use RegionBuilder to create robust, screen-adaptive automation that works consistently across different environments and display configurations.