HtmlDialog là lớp cho tạo và tương tác với hộp thoại HTML bằng ruby.

Tạo hộp thoại HtmlDialog

Ví dụ tạo hộp thoại đơn giản:

dialog = UI::HtmlDialog.new(
  {
    :dialog_title => "Ví dụ HTML Dialog",   # tiêu đề hộp thoại
    :preferences_key => "xuanthulab.net",   #
    :scrollable => true,                    # cho phép cuộn
    :resizable => true,                     # cho phép thay đổi cỡ
    :width => 600,                          # chiều rộng, cao
    :height => 400,
    :left => 100,                           # vị trí, tọa độ góc trên trái
    :top => 100,
    :min_width => 50,
    :min_height => 50,
    :max_width =>1000,                      # chiều rộng, cao lớn nhất
    :max_height => 1000,
    # kiểu hộp thoại UI::HtmlDialog::STYLE_UTILITY, UI::HtmlDialog::STYLE_WINDOW
    :style => UI::HtmlDialog::STYLE_DIALOG
  })
  # thiết lập Url
  dialog.set_url("https://xuanthulab.net")
  # thiết lập HTML của hộp thoại nếu muốn
  # dialog.set_html("<h1>xuanthulab.net</h1>")
dialog.show

Sửa đổi HtmlDialog

Sau khi có đối tượng HtmlDialog được tạo, có các phương thức để chỉnh sửa đổi tượng được tạo ra:

set_html(html_string)
Phương thức để nạp nội dung HTML vào hộp thoại
set_position(left, top) ⇒ true
Thiết lập vị trí
set_size(width, height) ⇒ true
Thiết lập cỡ hộp thoại
set_url(url) ⇒ nil
Nạp HTML từ URL
#set_file(filename) ⇒ nil
Nạp HTML từ file

Ví dụ có nội dung html lưu trong file file1.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Ví dụ HTML</title>
</head>
<body style="background-color: #00bcd4;">
    <h1>Xin chào, đây là nội dung HTML</h1>
</body>
</html>

Sử dụng nạp vào hộp thoại

dialog = UI::HtmlDialog.new(
{
  :dialog_title => "Ví dụ HTML Dialog",
  :preferences_key => "xuanthulab.net",
  :scrollable => true,
  :resizable => true,
  :width => 300,
  :height => 200,
  :left => 100,
  :top => 100,
  :min_width => 50,
  :min_height => 50,
  :max_width =>500,
  :max_height => 300,
  :style => UI::HtmlDialog::STYLE_DIALOG
})

dialog.set_file(__dir__ + '/file1.html')
dialog.show

JavaScript, CSS trong HtmlDialog

Các nội dung HTMl trong HtmlDialog có thể tích hợp CSS, JavaScript. Học về CSS tại CSS, học JavaScript tại JavaScript

Ví dụ có HTML có tích hợp CSS, JavaScript trong file2.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Ví dụ HTML</title>
  <style>
      #body {
        background-color:bisque;
        color: #333;
      }

  </style>
  <script>
       var i = 0;
       function addcontent()
       {
           i++;
           alert("Sẽ thêm nội dung HTML");
           let bd = document.getElementById('body');
           var n = document.createElement("p");
           n.textContent = "Nội dung chèn vào " + i;
           bd.prepend(n);
       }
  </script>
</head>
<body id="body">
    <h1>Xin chào, đây là nội dung HTML</h1>
    <input type="button" value="Thêm nội dung" onclick="addcontent();" />
</body>
</html>

Sau đó nạp nội dung này vào HtmlDialog

Tương tác qua lại JavaScript và SketchUp Ruby

Chạy JavaScript từ Ruby

Có thể thi hành một đoạn JavaScript lưu trong một chuỗi (không thẻ script) bằng cách gọi execute_script(script), ví dụ sau, khi nhấn chọn face hoặc cung tròn thì nó sẽ thi hành một script để thiết lập nội dung hộp thoại

# 28.ruby-call-js.rb
# load "/Users/xuanthulab/Desktop/learn-ruby/sketchup/28.ruby-call-js.rb"
require 'sketchup.rb'
require 'extensions.rb'




class SelObserver < Sketchup::SelectionObserver
  @entityselect = nil
  # @param [Sketchup::Entity] e
  def showinfomation(e)
    @entityselect = e
    puts e.class.to_s
    s = ''
    # @type [Sketchup::ArcCurve]
    curve = nil
    curve = e.curve if e.class.to_s == 'Sketchup::Edge'
    if curve
      #  curve.edges.each {|x| puts x}
      puts curve.class
      if curve.class.to_s == 'Sketchup::ArcCurve'
         if  (curve.end_angle - curve.start_angle).abs  == 2 * Math::PI
            s += "<h1>Hinh tròn</h1>"
         else
            s += "<h1>Cung tròn</h1>"
         end
      end
      s += "<h2>Phân đoạn: #{curve.edges.length}</h2>"
      s += "<h2>Chiều dài: #{curve.length.to_mm}</h2>"
    else
      # Face
      if e.class.to_s == 'Sketchup::Face'
        # @type [Sketchup::Face]
        face = e
        s += "<h1>Mặt - Face</h1>"
        s += "<h2>Pháp tuyến: #{face.normal.to_s}</h2>"
        s += "<h2>Diện tích: #{face.area.to_mm.to_mm}</h2>"
        s += "<h2>Phân đoạn: #{face.edges.length}</h2>"
      end

    end
    s = 'Chọn cung tròn hoặc mặt!' if s == ''

    # Đưa vào Hộp thoại
    $dialoginfo.execute_script("setBodyContent('#{s}')")
  end

  def onSelectionBulkChange(selection)
      first_ent = selection[0]
      if ! (first_ent.equal? @entityselect)
        showinfomation first_ent
      end

  end
end

sel = Sketchup.active_model.selection
if defined?($selob)
  puts "Remove Observer"
  sel.remove_observer $selob
end
$selob = SelObserver.new
sel.add_observer $selob

$dialoginfo = UI::HtmlDialog.new(
  {
    :dialog_title => "Ví dụ HTML Dialog",
    :preferences_key => "xuanthulab.net",
    :scrollable => true,
    :resizable => true,
    :width => 300,
    :height => 200,
    :left => 100,
    :top => 100,
    :min_width => 50,
    :min_height => 50,
    :max_width =>500,
    :max_height => 300,
    :style => UI::HtmlDialog::STYLE_DIALOG
  })


  $dialoginfo.set_file(__dir__ + '/28.ruby-call-js.html')
  $dialoginfo.show
28.ruby-call-js.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
      #body {
        background-color:bisque;
        color: #333;
      }

  </style>
  <script>

       function setBodyContent(s)
       {
          bd = document.getElementById('body');
          bd.innerHTML = s;

       }
  </script>
</head>
<body id="body">
    <h1>Xin chào, đây là nội dung HTML</h1>
</body>
</html>

Chạy Ruby từ JavaScript

Cú pháp để khai báo một callback (phương thức) Ruby - mà có thể gọi được từ JavaScript thì sử dụng add_action_callback của HtmlDialog như sau:

add_action_callback(callback_name) {|action_context, param1, param2, pram3 ... }

Lúc này trong Js có thể gọi callback_name(param1, param2, pram3, ...), chú ý phần khai báo có action_context hiện không được dùng đến, với cú pháp cụ thể:

sketchup.callback_name(param1, param2, pram3, {
  onCompleted: function() {
    console.log('Ruby side done.');
  }
});

Ví dụ khai báo phương thức callback create_face tạo mặt từ bốn điểm nhập vào:

# 29.js_call_ruby.rb
# load "/Users/xuanthulab/Desktop/learn-ruby/sketchup/29.js_call_ruby.rb"
require 'sketchup.rb'
require 'extensions.rb'

 if defined? $dialoginfo
    $dialoginfo.close
 end
$dialoginfo = UI::HtmlDialog.new(
  {
    :dialog_title => "Ví dụ HTML Dialog",
    :preferences_key => "xuanthulab.net",
    :scrollable => true,
    :resizable => true,
    :width => 300,
    :height => 400,
    :left => 100,
    :top => 100,
    :min_width => 50,
    :min_height => 50,
    :max_width =>500,
    :max_height => 400,
    :style => UI::HtmlDialog::STYLE_DIALOG
  })


  $dialoginfo.set_file(__dir__ + '/29.js_call_ruby.html')




  $dialoginfo.add_action_callback("create_face") {|action_context, points|
    # @type [Array] points
    # points.each {
    #    |e|
    #    # @type [Hash] e
    #  }


    pt1 = Geom::Point3d.new(Float(points[0]['x'].strip).mm, Float(points[0]['y'].strip).mm, Float(points[0]['z'].strip).mm)
    pt2 = Geom::Point3d.new(Float(points[1]['x'].strip).mm, Float(points[1]['y'].strip).mm, Float(points[1]['z'].strip).mm)
    pt3 = Geom::Point3d.new(Float(points[2]['x'].strip).mm, Float(points[2]['y'].strip).mm, Float(points[2]['z'].strip).mm)
    pt4 = Geom::Point3d.new(Float(points[3]['x'].strip).mm, Float(points[3]['y'].strip).mm, Float(points[3]['z'].strip).mm)

    vec1 = pt2 - pt1
    vec2 = pt2 - pt3
    plane = [pt1, vec1 * vec2]

    if pt4.on_plane? plane
      Sketchup.active_model.entities.add_face pt1, pt2, pt3, pt4
    else
      puts "Invalid input. Points must lie on the same plane."
    end

  }


  $dialoginfo.show

Nội dung file HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

  <script>

       function send()
       {

        let points = Array();
        for (let index = 1; index <= 4; index++) {
            let point = {}
            point["x"] = document.getElementById('x' + index).value
            point["y"] = document.getElementById('y' + index).value
            point["z"] = document.getElementById('z' + index).value
            points.push(point)
        }
        sketchup.create_face(points, {
            onCompleted: function(ob) {
            }
          });

       }
  </script>
</head>
<body>
    <div class="container pt-3">
       <div class="card w-100">
          <div class="card-body">
            <p><strong>Tạo mặt từ các điểm</strong></p>
            <!-- Location of the first vertex -->
                Điểm 1:
                <input type="text" id="x1" value="0.0" size="10" maxlength="6"/> <input type="text" id="y1" value="0.0" size="10" maxlength="6"/> <input type="text" id="z1" value="0.0" size="10" maxlength="6"/> <br /><br />
                <!-- Location of the second vertex -->
                Điểm 2:
                <input type="text" id="x2" value="10.0" size="10" maxlength="6"/> <input type="text" id="y2" value="0.0" size="10" maxlength="6"/> <input type="text" id="z2" value="0.0" size="10" maxlength="6"/> <br /><br />
                <!-- Location of the third vertex -->
                Điểm 3:
                <input type="text" id="x3" value="10.0" size="10" maxlength="6"/> <input type="text" id="y3" value="10.0" size="10" maxlength="6"/> <input type="text" id="z3" value="0.0" size="10" maxlength="6"/> <br /><br />
                <!-- Location of the fourth vertex -->
                Điểm 4:
                <input type="text" id="x4" value="0.0" size="10" maxlength="6"/> <input type="text" id="y4" value="10.0" size="10" maxlength="6"/> <input type="text" id="z4" value="0.0" size="10" maxlength="6"/> <br /><br />
            <input class="btn btn-success" type="button" onclick="send()" value="Tạo Face">
          </div>
       </div>
    </div>
</body>
</html>
Đăng ký theo dõi ủng hộ kênh