This is a simple HTML browser built using pyWebLayout components.
Bold text, italic text, and underlined text
Sample link: Visit Example.com
Use the "Open File" button to load local HTML files.
Or enter a URL in the address bar above.
""" parser = HTMLParser() self.current_page = parser.parse_html_string(html_content) self.render_page() self.status_var.set("Welcome page loaded") def navigate_to_url(self, event=None): """Navigate to the URL in the address bar""" url = self.url_var.get().strip() if not url: return self.status_var.set(f"Loading {url}...") self.root.update() try: if url.startswith(('http://', 'https://')): # Web URL response = requests.get(url, timeout=10) response.raise_for_status() html_content = response.text parser = HTMLParser() self.current_page = parser.parse_html_string(html_content, url) elif os.path.isfile(url): # Local file parser = HTMLParser() self.current_page = parser.parse_html_file(url) else: # Try to treat as a local file path if not url.startswith('file://'): url = 'file://' + os.path.abspath(url) file_path = url.replace('file://', '') if os.path.isfile(file_path): parser = HTMLParser() self.current_page = parser.parse_html_file(file_path) else: raise FileNotFoundError(f"File not found: {file_path}") # Add to history self.add_to_history(url) self.render_page() self.status_var.set(f"Loaded {url}") except Exception as e: self.status_var.set(f"Error loading {url}: {str(e)}") messagebox.showerror("Error", f"Failed to load {url}:\n{str(e)}") def open_file(self): """Open a local HTML file""" file_path = filedialog.askopenfilename( title="Open HTML File", filetypes=[("HTML files", "*.html *.htm"), ("All files", "*.*")] ) if file_path: self.url_var.set(file_path) self.navigate_to_url() def render_page(self): """Render the current page to the canvas""" if not self.current_page: return # Clear canvas self.canvas.delete("all") # Render the page to PIL Image page_image = self.current_page.render() # Convert to PhotoImage self.photo = ImageTk.PhotoImage(page_image) # Display on canvas self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo) # Update scroll region self.canvas.configure(scrollregion=self.canvas.bbox("all")) # Store page elements for interaction self.page_elements = self._get_clickable_elements(self.current_page) def _get_clickable_elements(self, container, offset=(0, 0)) -> List[Tuple]: """Get list of clickable elements with their positions""" elements = [] if hasattr(container, '_children'): for child in container._children: if hasattr(child, '_origin'): child_offset = (offset[0] + child._origin[0], offset[1] + child._origin[1]) # Check if element is clickable if isinstance(child, (RenderableLink, RenderableButton)): elements.append((child, child_offset, child._size)) # Recursively check children if hasattr(child, '_children'): elements.extend(self._get_clickable_elements(child, child_offset)) return elements def on_click(self, event): """Handle mouse clicks on the canvas""" # Convert canvas coordinates to image coordinates canvas_x = self.canvas.canvasx(event.x) canvas_y = self.canvas.canvasy(event.y) # Check if click is on any clickable element for element, offset, size in self.page_elements: element_x, element_y = offset element_w, element_h = size if (element_x <= canvas_x <= element_x + element_w and element_y <= canvas_y <= element_y + element_h): # Handle the click if isinstance(element, RenderableLink): result = element._callback() if result: self.status_var.set(result) # For external links, open in system browser if element._link.link_type == LinkType.EXTERNAL: webbrowser.open(element._link.location) elif isinstance(element, RenderableButton): result = element._callback() if result: self.status_var.set(f"Button clicked: {result}") break def on_mouse_move(self, event): """Handle mouse movement for hover effects""" # Convert canvas coordinates to image coordinates canvas_x = self.canvas.canvasx(event.x) canvas_y = self.canvas.canvasy(event.y) # Check if mouse is over any clickable element cursor = "arrow" for element, offset, size in self.page_elements: element_x, element_y = offset element_w, element_h = size if (element_x <= canvas_x <= element_x + element_w and element_y <= canvas_y <= element_y + element_h): cursor = "hand2" break self.canvas.configure(cursor=cursor) def add_to_history(self, url): """Add URL to navigation history""" # Remove any forward history self.history = self.history[:self.history_index + 1] # Add new URL self.history.append(url) self.history_index = len(self.history) - 1 # Update navigation buttons self.update_nav_buttons() def update_nav_buttons(self): """Update the state of navigation buttons""" self.back_btn.configure(state=tk.NORMAL if self.history_index > 0 else tk.DISABLED) self.forward_btn.configure(state=tk.NORMAL if self.history_index < len(self.history) - 1 else tk.DISABLED) def go_back(self): """Navigate back in history""" if self.history_index > 0: self.history_index -= 1 url = self.history[self.history_index] self.url_var.set(url) self.navigate_to_url() def go_forward(self): """Navigate forward in history""" if self.history_index < len(self.history) - 1: self.history_index += 1 url = self.history[self.history_index] self.url_var.set(url) self.navigate_to_url() def refresh(self): """Refresh the current page""" if self.current_page: current_url = self.url_var.get() if current_url: self.navigate_to_url() else: self.load_default_page() def run(self): """Start the browser""" self.root.mainloop() def main(): """Main function to run the browser""" print("Starting pyWebLayout HTML Browser...") try: browser = BrowserWindow() browser.run() except Exception as e: print(f"Error starting browser: {e}") import traceback traceback.print_exc() if __name__ == "__main__": main()