Skip to content

Commit

Permalink
Merge pull request #9 from fedoraman737/port
Browse files Browse the repository at this point in the history
Draw function logic improvements - recentering bug fix
  • Loading branch information
fedoraman737 authored Aug 10, 2024
2 parents 256a740 + c50b26f commit 256b10b
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 19 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ set(SOURCES
src/NetworkMap.cpp
src/FileSelector.c
src/DashVisual.cpp
src/PortAnalysis.cpp
)

# Add sources with headers
Expand Down
46 changes: 46 additions & 0 deletions src/DashVisual.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ DashVisual::DashVisual(float width, float height) {

// Set the first button as active
visualizeBtn.setFillColor(sf::Color(139, 0, 0)); // Dark red for active button
activeButtonText = "Network Map"; // Track the active button text
}

void DashVisual::initButton(sf::RectangleShape &button, const std::string &text, float yPos, bool isActive) {
Expand Down Expand Up @@ -69,6 +70,7 @@ void DashVisual::draw(sf::RenderWindow &window) {
window.setView(window.getDefaultView()); // Reset to default view to draw fixed elements

handleMouseHover(window); // Handle hover effect before drawing
handleMouseClick(window); // Handle mouse click to switch active button

window.draw(dashboard);

Expand Down Expand Up @@ -102,3 +104,47 @@ void DashVisual::handleMouseHover(const sf::RenderWindow &window) {
}
}

void DashVisual::handleMouseClick(sf::RenderWindow &window) {
static bool isMouseButtonHeld = false; // Track whether the mouse button is held down

if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
if (!isMouseButtonHeld) { // Check if this is the first detection of the click
isMouseButtonHeld = true; // Mark the button as held

sf::Vector2i mousePos = sf::Mouse::getPosition(window);

if (visualizeBtn.getGlobalBounds().contains(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y))) {
if (activeButtonText != "Network Map") {
activeButtonText = "Network Map"; // Set the active button text first
setActiveButton(visualizeBtn);
}
} else if (analyzeBtn.getGlobalBounds().contains(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y))) {
if (activeButtonText != "Port Analysis") {
activeButtonText = "Port Analysis"; // Set the active button text first
setActiveButton(analyzeBtn);
}
} else if (helpBtn.getGlobalBounds().contains(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y))) {
if (activeButtonText != "Vulnerability Insights") {
activeButtonText = "Vulnerability Insights"; // Set the active button text first
setActiveButton(helpBtn);
}
}
}
} else {
isMouseButtonHeld = false; // Reset when the mouse button is released
}
}

void DashVisual::setActiveButton(sf::RectangleShape &button) {
// Reset all buttons to default grey before updating the active one
for (auto &btn : buttons) {
btn.setFillColor(sf::Color(100, 100, 100));
}

// Set the clicked button to dark red
button.setFillColor(sf::Color(139, 0, 0));
}

bool DashVisual::isActiveButton(const std::string &buttonText) const {
return activeButtonText == buttonText;
}
10 changes: 9 additions & 1 deletion src/DashVisual.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ class DashVisual {
void loadFont(const std::string &fontPath);
void draw(sf::RenderWindow &window);

// New methods for managing active buttons
void handleMouseClick(sf::RenderWindow &window);
void setActiveButton(sf::RectangleShape &button);
bool isActiveButton(const std::string &buttonText) const;

private:
sf::RectangleShape dashboard;
sf::RectangleShape visualizeBtn;
Expand All @@ -28,8 +33,11 @@ class DashVisual {
sf::Font font;
bool fontLoaded = false;

// Store the active button's text
std::string activeButtonText;

void initButton(sf::RectangleShape &button, const std::string &text, float yPos, bool isActive);
void handleMouseHover(const sf::RenderWindow &window);
};

#endif // DASHVISUAL_H
#endif // DASHVISUAL_H
37 changes: 22 additions & 15 deletions src/NetworkMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,32 +51,39 @@ void NetworkMap::calculatePanLimits() {
}

void NetworkMap::draw(sf::RenderWindow& window) {
window.setView(view);
// Set view initially if it hasn't been centered yet
if (!isViewCenteredInitially && !hosts.empty()) {
// Determine the center of the window (this will be the initial position for the root node)
float centerX = static_cast<float>(window.getSize().x) / 2.0f;
float centerY = static_cast<float>(window.getSize().y) / 2.0f;

if (hosts.empty()) {
return;
}
// Assume the first host is the gateway/modem and initially position it at the center
hostPositions[hosts[0].ip] = sf::Vector2f(centerX, centerY);

// Determine the center of the window (this will be the initial position for the root node)
float centerX = static_cast<float>(window.getSize().x) / 2.0f;
float centerY = static_cast<float>(window.getSize().y) / 2.0f;
// Position the other hosts using the force-directed algorithm
positionHostsUsingForceDirected(centerX, centerY);

// Assume the first host is the gateway/modem and initially position it at the center
hostPositions[hosts[0].ip] = sf::Vector2f(centerX, centerY);
// Set the view to be centered on the root node
sf::Vector2f rootPosition = hostPositions[hosts[0].ip];
view.setCenter(rootPosition);

// Position the other hosts using the force-directed algorithm
positionHostsUsingForceDirected(centerX, centerY);
isViewCenteredInitially = true; // Mark that the view has been centered
}

// Now adjust the view to center it on the root node's actual position
sf::Vector2f rootPosition = hostPositions[hosts[0].ip];
view.setCenter(rootPosition);
window.setView(view);

if (hosts.empty()) {
return;
}

// Draw the connections and nodes
drawConnections(window);
drawNodes(window);
drawHostDetails(window);
}



void NetworkMap::positionHostsUsingForceDirected(float centerX, float centerY) {
const float repulsiveForceStrength = 2000.0f;
const float damping = 0.85f;
Expand Down Expand Up @@ -382,4 +389,4 @@ void NetworkMap::handleNodeHover(sf::RenderWindow& window, const sf::Vector2i& m
break;
}
}
}
}
1 change: 1 addition & 0 deletions src/NetworkMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class NetworkMap {
sf::FloatRect panLimits;
std::unordered_map<std::string, sf::Vector2f> hostPositions;
std::unordered_map<std::string, sf::Vector2f> forces; // declare forces
bool isViewCenteredInitially = false;

void loadFont(const std::string& fontPath);
void calculatePanLimits();
Expand Down
132 changes: 132 additions & 0 deletions src/PortAnalysis.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include "PortAnalysis.h"
#include <sstream>
#include <iostream>

PortAnalysis::PortAnalysis(const std::vector<Host>& hosts) : hosts(hosts), currentInput("") {
loadFont("fonts/Roboto-Regular.ttf");

// Initialize the input box
inputBox.setSize(sf::Vector2f(200, 30));
inputBox.setFillColor(sf::Color(255, 255, 255));

// Initialize the input label
if (fontLoaded) {
inputLabel.setFont(font);
inputLabel.setCharacterSize(16);
inputLabel.setFillColor(sf::Color::Black);
inputLabel.setString("");
}

// Initialize the analyze button
analyzeButton.setSize(sf::Vector2f(100, 30));
analyzeButton.setFillColor(sf::Color(100, 100, 250));

// Initialize the analyze button text
if (fontLoaded) {
analyzeButtonText.setFont(font);
analyzeButtonText.setCharacterSize(16);
analyzeButtonText.setFillColor(sf::Color::White);
analyzeButtonText.setString("Analyze");
}

// Initialize the result text
if (fontLoaded) {
resultText.setFont(font);
resultText.setCharacterSize(16);
resultText.setFillColor(sf::Color::White);
resultText.setString("");
}
}

void PortAnalysis::loadFont(const std::string& fontPath) {
if (!font.loadFromFile(fontPath)) {
std::cerr << "Failed to load font from: " << fontPath << "\n";
fontLoaded = false;
} else {
fontLoaded = true;
std::cout << "Font loaded successfully from: " << fontPath << "\n";
}
}

void PortAnalysis::draw(sf::RenderWindow &window) {
window.setView(window.getDefaultView()); // Reset the view to default
window.clear(sf::Color::Black); // Clear the window with a black color

// Center the input box and button
sf::Vector2u windowSize = window.getSize();
float centerX = windowSize.x / 2.0f;

inputBox.setPosition(centerX - inputBox.getSize().x - 10, windowSize.y / 2.0f - inputBox.getSize().y / 2.0f);
inputLabel.setPosition(inputBox.getPosition().x + 10, inputBox.getPosition().y + 5);

analyzeButton.setPosition(centerX + 10, windowSize.y / 2.0f - analyzeButton.getSize().y / 2.0f);
analyzeButtonText.setPosition(analyzeButton.getPosition().x + 10, analyzeButton.getPosition().y + 5);

// Position the result text below the input box and button
resultText.setPosition(centerX - resultText.getLocalBounds().width / 2.0f, analyzeButton.getPosition().y + 50);

// Draw the input box, button, and result text
window.draw(inputBox);
window.draw(inputLabel);
window.draw(analyzeButton);
window.draw(analyzeButtonText);
window.draw(resultText);
}

void PortAnalysis::handleEvents(sf::RenderWindow &window, const sf::Event &event) {
if (event.type == sf::Event::TextEntered) {
handleTextInput(event);
} else if (event.type == sf::Event::MouseButtonPressed) {
handleMouseClick(event, window);
}
}

void PortAnalysis::handleTextInput(const sf::Event& event) {
// Handle backspace
if (event.text.unicode == 8 && !currentInput.empty()) {
currentInput.pop_back();
}
// Handle regular character input
else if (event.text.unicode < 128 && event.text.unicode != 8) {
currentInput += static_cast<char>(event.text.unicode);
}

inputLabel.setString(currentInput);
}

void PortAnalysis::handleMouseClick(const sf::Event& event, sf::RenderWindow &window) {
sf::Vector2f mousePos = window.mapPixelToCoords(sf::Mouse::getPosition(window));

// Check if the analyze button is clicked
if (analyzeButton.getGlobalBounds().contains(mousePos)) {
analyzeIP(currentInput);
}
}

void PortAnalysis::analyzeIP(const std::string& ip) {
std::vector<std::string> openPorts;

for (const auto& host : hosts) {
if (host.ip == ip) {
openPorts = host.openPorts;
break;
}
}

if (openPorts.empty()) {
resultText.setString("No open ports found for IP: " + ip);
} else {
resultText.setString("Open ports for IP: " + ip + " -> " + joinOpenPorts(openPorts));
}
}

std::string PortAnalysis::joinOpenPorts(const std::vector<std::string>& ports) {
std::string result;
for (size_t i = 0; i < ports.size(); ++i) {
if (i > 0) {
result += ", "; // Separate ports with a comma
}
result += ports[i];
}
return result;
}
35 changes: 35 additions & 0 deletions src/PortAnalysis.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef PORTANALYSIS_H
#define PORTANALYSIS_H

#include <SFML/Graphics.hpp>
#include <vector>
#include <string>
#include "Host.h"

class PortAnalysis {
public:
PortAnalysis(const std::vector<Host>& hosts);
void draw(sf::RenderWindow &window);
void handleEvents(sf::RenderWindow &window, const sf::Event &event);

private:
const std::vector<Host>& hosts;
sf::Font font;
bool fontLoaded;

sf::Text inputLabel;
sf::Text analyzeButtonText;
sf::Text resultText;
sf::RectangleShape inputBox;
sf::RectangleShape analyzeButton;

std::string currentInput;

void loadFont(const std::string& fontPath);
void handleTextInput(const sf::Event& event);
void handleMouseClick(const sf::Event& event, sf::RenderWindow &window);
void analyzeIP(const std::string& ip);
std::string joinOpenPorts(const std::vector<std::string>& ports);
};

#endif // PORTANALYSIS_H
24 changes: 21 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <iostream>
#include <exception>
#include <fstream>
#include "PortAnalysis.h"

int main() {
try {
Expand Down Expand Up @@ -38,19 +39,36 @@ int main() {
dashVisual.loadFont("fonts/Roboto-Regular.ttf");

NetworkMap networkMap(hosts);
PortAnalysis portAnalysis(hosts);

while (window.isOpen()) {
sf::Event event{};
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();

networkMap.handleEvents(window, event);
// Handle events based on the active view
if (dashVisual.isActiveButton("Network Map")) {
networkMap.handleEvents(window, event);
} else if (dashVisual.isActiveButton("Port Analysis")) {
portAnalysis.handleEvents(window, event);
}
}

// Clear the window once per frame
window.clear();
networkMap.draw(window); // Draw the network map
dashVisual.draw(window); // Draw the fixed dashboard last

// Draw based on the active view
if (dashVisual.isActiveButton("Network Map")) {
networkMap.draw(window);
} else if (dashVisual.isActiveButton("Port Analysis")) {
portAnalysis.draw(window);
}

// Draw the dashboard last to ensure it stays on top
dashVisual.draw(window);

// Display the rendered frame
window.display();
}

Expand Down

0 comments on commit 256b10b

Please sign in to comment.